rslib-modern-package について
Rslibを使うJavaScript/TypeScriptライブラリの作成、モダナイズ、レビュー向けスキルです。公開API、型、依存関係、リリース、公開成果物の検証を詳しい基準に沿って扱います。
主な機能
- 01ESM優先のパッケージ設計指針
- 02package.json exportsの明示
- 03TypeScript宣言と厳格性の確認
- 04依存関係と副作用のレビュー
- 05成果物とリリースの検証
活用シーン
- 01新しいRslibライブラリの作成
- 02既存JS/TSパッケージのモダナイズ
- 03パッケージの公開設定と型宣言のレビュー
- 04公開前のパッケージ検査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ rstackjs/ agent-skills --skill rslib-modern-packageインストール後、Claude Code で/rslib-modern-packageを入力して読み込まれたか確認します。
詳細
Rslib モダンパッケージ
新しい Rslib ライブラリの作成、既存の JS/TS パッケージのモダン化、またはパッケージが独自のモダンライブラリ標準に準拠しているかのレビューに、このスキルを使用してください。
このスキルには独自の推奨方針があります。モダンなパッケージに推奨される契約を示し、パッケージをよりシンプルで安全にし、モダンな利用者が使いやすくなる場合は、破壊的変更を提案することがあります。
標準
新しい JS/TS ライブラリでは、以下をデフォルトとして推奨します。
- ESM を優先し、可能であれば純粋な ESM にします。
- TypeScript を厳格に設定し、正確な型定義ファイルを用意します。
package.json#exportsを通じてパブリック API を明示します。- 名前付きエクスポートを中心に、API の公開範囲を小さく保ちます。
- ランタイム依存関係を最小限にします。ただし、依存関係ゼロを絶対視しません。
- 出力を小さく、ツリーシェイキング可能にし、
sideEffectsを正確に設定します。 - 依存関係を適切に配置します。ランタイム依存関係、ピア依存関係、オプション依存関係、開発依存関係は互いに置き換え可能ではありません。
- 公開するパッケージは、ソースファイルだけでなく、成果物としてテストします。
- リリースフローを自動化し、追跡可能にして、SemVer を考慮します。
- README.md では人間向けに使い方を説明し、AGENTS.md では今後のエージェント向けにパッケージの不変条件を保持します。
ワークフロー
-
まずパッケージの契約を確認します
package.json、ロックファイル/パッケージマネージャー、rslib.config.*、tsconfig*、CI/リリース設定、README.md、AGENTS.md、既存のdist出力を読みます。- パッケージの種類を特定します。Node ユーティリティ、ブラウザーライブラリ、アイソモーフィックユーティリティ、CLI、UI/コンポーネントライブラリ、フレームワークプラグイン、SDK、アダプターなどです。
- サポート対象のランタイム、現在のエントリーポイント、ディープインポート、ランタイム依存関係、ピア依存関係、オプションの連携機能、副作用のあるファイル、公開対象ファイルを一覧にします。
- パッケージの構成を変更する場合は、早い段階で
npm pack --dry-runを実行し、実際の tarball の内容をレビューの指針にします。
-
対象環境を明確に定義します
- 定義せずに「モダンな環境をサポートする」とは言わないでください。
enginesを選ぶ前に、現在の Node.js リリーススケジュールを確認します。- 2026 年 5 月 9 日時点では、Node.js 22 と 24 が LTS で、Node.js 20 は EOL です。新しい Node.js 向けパッケージでは、実際の利用者が古いランタイムを必要としない限り、
engines.node >=22を推奨します。 - ブラウザー向けパッケージでは、ネイティブ ESM、バンドラー、Workers のサポート、SSR 互換性、DOM API、CSS 処理、特定のブラウザーバージョンのどれが必要かを明記します。
- 互換性の対象を外すことは破壊的変更です。古い Node.js/ブラウザーのバージョン、文書化されていないディープインポート、デフォルト/名前付きエクスポートの形式、依存関係のバンドルと外部化の挙動、インポート時の副作用が該当します。
-
純粋な ESM を優先します。ただし、互換性に伴うコストを説明します
- 新しいパッケージでは
"type": "module"と ESM のソース/出力を使用します。 - Rslib のデフォルト形式は ESM です。別の形式を追加する明確な理由がない限り、デフォルトのままにします。
- 過去のすべてのモジュール形式が必要だと決めつけず、実際の利用者とサポート対象のランタイムに基づいて互換性を評価します。
- モダンな Node.js は CommonJS から
require(esm)を介して同期的な ESM を読み込めます。CommonJS の利用者には常に別個の CJS ビルドが必要だと決めつけないでください。 require(esm)との互換性に依存する場合は、その制約を文書化してテストします。サポート対象の Node.js バージョン、読み込み対象のモジュールグラフでトップレベルawaitを使用しないこと、名前空間オブジェクトの戻り値の形式、デフォルトエクスポートの挙動、CJS/ESM の循環依存に関する制限です。node:fs/promisesなどの Node.js 組み込みモジュールの指定子を優先します。
- 新しいパッケージでは
-
exportsを公開 API にするpackage.json#exportsを製品の契約として扱います。- ユーザーがインポートすることを想定したパスのみをエクスポートします。
./dist/*をエクスポートしてpkg/dist/foo.jsのようなインポートを許可しないでください。生成された出力の構成が公開 API の一部となり、内部ファイルの移動が破壊的変更になります。- 代わりに、
pkgやpkg/foo.jsのような意図した公開パスのみを、dist内の実際のファイルにマッピングして公開します。 - サブパスの形式を統一します。
./foo.jsのように拡張子を付ける形式と、付けない形式のどちらかに統一してください。ブラウザーのインポートマップを考慮する場合は、拡張子付きのパスを推奨します。 - 条件付きエクスポート内では
"types"を先頭に置きます。 - 古いパッケージに
exportsを追加すると、宣言されていない深いインポートが機能しなくなるため、破壊的変更となることがあります。 - 利用者がパッケージのメタデータを正当に必要とする場合に限り、
./package.jsonを追加します。
-
小さな API サーフェスを設計する
- 複数の API を持つパッケージでは、名前付きエクスポートを優先します。
- すべての関数を 1 つのオブジェクトにまとめたデフォルトエクスポートは避けます。
- 公開関数は少数にし、安定性を保ち、適切な名前を付けて、セマンティックバージョニングに基づいて保守します。
- 内部型、キャッシュ、ヘルパー関数、アダプターの詳細、エラーの内部実装は、契約の一部でない限り非公開にします。
- インポート時にトップレベルで処理を実行しないでください。ファイルのスキャン、ネットワーク呼び出し、タイマー、プロセスの変更、グローバルへの登録、DOM へのアクセス、プロトタイプの変更、副作用を伴う環境検出などが該当します。
- キャンセル可能な非同期 API では、
AbortSignalを受け取るようにします。 - 文字列の照合よりも、安定したエラークラス、エラーコード、または型付きのエラー形式を優先します。
-
実装手段として Rslib を使い、規約全体とはみなさない
- Rslib の詳細な設定方法については、
rslib-best-practicesスキルを使用します。 - このスキルでは、Rslib の出力、宣言ファイル、
package.json#exports、files、依存関係、ドキュメントが最新のパッケージ契約と整合しているかどうかだけを確認します。 - Rslib の設定は小さく、意図を明確にします。パッケージ契約の改善につながらないビルドの複雑化は避けます。
- Rslib の詳細な設定方法については、
-
依存関係は少なく、必要なものに絞る
- 依存パッケージを探すのではなく、プラットフォーム API を起点にします。
- 実行環境が対応している場合は、組み込み機能を優先します。
URL、URLSearchParams、Intl、fetch、AbortController、structuredClone、crypto.randomUUID、Web Streams、TextEncoder、TextDecoder、node:fs/promises、node:cryptoが該当します。 - 保守上のリスクや実装の複雑さを軽減できる場合は、小規模なランタイム依存関係を追加しても問題ありません。
- 1、2 個のヘルパーのために、大規模なユーティリティパッケージを使うのは避けます。
- 依存関係について、ESM 対応状況、
exports、型定義、推移的依存関係の数、パッケージサイズ、ライセンス、メンテナンスの状況、セキュリティ履歴、インストールスクリプト、副作用、ネイティブ依存関係のインストールの不安定さ、粒度の細かいインポートに対応しているかを評価します。 - 必須のランタイムパッケージは
dependenciesに指定します。 - React、Vue、Svelte、Rspack、Rsbuild、webpack、TypeScript、フレームワークのランタイムなど、ホスト側が所有するフレームワークやツールチェーンは
peerDependenciesに指定します。 - peer のバージョン範囲は適切に広く保ちます。必要でない限り、peer をパッチバージョンに固定しないでください。
- ビルドツール、テストツール、型ツール、ドキュメントツール、Rsbuild/Rspack プラグインは
devDependenciesに指定します。 - 任意の連携機能には、
optionalDependenciesまたはpeerDependenciesMetaを使った optional peer を指定します。
-
TypeScript を厳格にし、パッケージ指向にする
- TS ライブラリでは TypeScript のソースを優先します。それ以外の場合は、高品質な JSDoc と生成された宣言を使用します。
- TypeScript 6 または tsgo 時代のデフォルトでは、すでに厳格なチェックが有効になっている場合があります。そのデフォルトを維持し、無効にしないでください。古い TypeScript バージョンや設定を継承している場合は、
strict: trueを明示的に設定します。 - Rslib プロジェクトでは、tsgo を使用できる場合、宣言生成を高速化するために
lib.dts.tsgoを有効にすることを検討してください。 - 宣言の出力方法と、利用側でのパッケージの解決方法に合わせて、
moduleとmoduleResolutionを設定します。適切なツールチェーンであれば、NodeNext とバンドラー形式の解決はいずれも有効です。 - 型のみのインポート/エクスポートを明示するため、
verbatimModuleSyntaxを使用します。 - 実用上可能な場合は
isolatedDeclarationsを使用し、宣言指向のツールで扱えるよう、エクスポートする API を十分に明示します。 - 宣言を出力します。エディターでの定義への移動が重要な場合は、宣言マップを使用します。
- 型のみの依存関係には
import typeとexport typeを使用します。 - 壊れたパッケージ型を隠すために、利用者が
skipLibCheckを設定することに依存しないでください。 - 特にサブパスエクスポートを使用する場合は、利用者から見た宣言をテストします。
-
sideEffectsを正確に保つ- パッケージファイルのインポート時にトップレベルの副作用がない場合に限り、
sideEffects: falseを使用します。 - CSS、ポリフィル、登録処理、グローバルリスナー、プロトタイプの変更、その他のインポート時の変更がある場合は、副作用のあるファイルを代わりに列挙します。
- バンドルサイズを改善するためだけに
sideEffects: falseを設定しないでください。不正確な値によって、必要な CSS やセットアップコードが削除されることがあります。 - ファイルがインポートされたことだけを理由に、グローバルを変更しないでください。セットアップが必要な場合は、明示的な
setup()またはinstall()関数を公開し、利用者自身が呼び出せるようにします。
- パッケージファイルのインポート時にトップレベルの副作用がない場合に限り、
-
package.jsonを信頼できる唯一の情報源にする- 必須の最新形式は、
"type": "module"、明示的なexports、正しい宣言、filesの許可リスト、正確なsideEffects、妥当なengines、リリース用スクリプトです。 - README.md、AGENTS.md、LICENSE がある場合は、
filesに含めます。 filesにより、テスト、フィクスチャ、非公開ドキュメント、ビルドキャッシュ、ローカル設定、大きな生成済み成果物が tarball に漏れないようにします。- 互換性に関する根拠がない限り、古くなった
main/moduleフィールドは避けます。残す場合は、exportsと一致させる必要があります。 - ランタイム依存関係のフィールドを正確に保ちます。ランタイム依存関係が
devDependenciesにあるためにローカルでしか動作しないパッケージは、壊れています。
- 必須の最新形式は、
-
公開する成果物を検証する
- 通常の lint、型チェック、テスト、
rslib buildを実行します。 - ビルド済みの ESM 出力をスモークテストします。
- 公開 API が型に大きく依存する場合は、型レベルのテストを実行します。
npm pack --dry-runを実行し、含まれるファイルを確認します。- Rslib では、ビルド後に publint を実行するため、
rsbuild-plugin-publintの使用を優先します。CLI の代替手段としてnpx publintを使用します。 - Rslib では、宣言を同梱する場合、ビルド後に Are The Types Wrong を実行するため、
rsbuild-plugin-arethetypeswrongの使用を優先します。CLI の代替手段としてnpx --yes @arethetypeswrong/cli --pack .を使用します。 - 重要なパッケージでは、クリーンな利用側のフィクスチャにパッケージ化した tarball をインストールします。
- ESM インポート、ブラウザー/コンポーネントライブラリのバンドラー経由のインポート、
binパッケージの CLI 実行、すべての公開サブパスエクスポートをテストします。
- 通常の lint、型チェック、テスト、
-
公開前にREADME.mdとAGENTS.mdを準備する
- パッケージを公開または最新化する前に、両方のファイルが存在するか必ず確認してください。
- いずれかのファイルがない場合は、追加を推奨してください。実装タスクでは、ユーザーから指示がない限り、簡潔なバージョンを作成してください。
- README.mdには、パッケージ名、目的を説明する一文、インストール方法と使用方法、主な機能またはAPIへのリンク、対応環境、ドキュメントや関連リンク、変更履歴またはコントリビューションへのリンク、ライセンスを記載してください。
- AGENTS.mdには、スタック、パッケージの契約、一般的なコマンド、ソースの構成、コードスタイル、検証コマンド、リリースチェックリストを記載してください。
- 両ファイルの内容を、
package.json#exports、対応ランタイム、実際のRslibの出力と同期させてください。
-
サプライチェーンの衛生管理を徹底して公開する
- SemVerに従い、破壊的変更を文書化してください。
- ユーザーに影響する変更の変更履歴を管理してください。
- ベータ版/nextチャンネルには、プレリリースバージョンとdist-tagを使用してください。
- npm provenanceまたは信頼できる公開機能を利用したCIからの公開を優先してください。
- 信頼できる公開機能を利用できる場合、長期間有効な公開トークンは避けてください。
- 公開済みのパッケージ名とバージョンの組み合わせは、安全に再利用できないことに留意してください。
レビュー時の危険信号
exportsがない、Rslibが出力しないファイルを参照している、またはpkg/dist/foo.jsのような公開インポートを許可している。module/mainフィールドがexportsと一致していない。- 型宣言がランタイムのエントリーポイントと一致していない。
- ランタイム依存関係が誤って
devDependenciesにのみ記載されている。 - React/Vue/Svelte/Rspack/Rsbuild/webpack/TypeScriptがバンドルされている、またはpeerにすべきところで
dependenciesに配置されている。 - CSS、ポリフィル、グローバル登録、グローバルリスナー、プロトタイプの変更をインポートしているにもかかわらず、
sideEffects: falseが設定されている。 - 強い理由もなく、インストールスクリプトが含まれている。
- トップレベルのインポートでユーザーファイルを読み取る、タイマーを開始する、ネットワークにアクセスする、グローバルを変更する、または
window/processを前提としている。 - 公開用tarballに、非公開のソースマップ、利用者にとって有用でないテスト/フィクスチャ、大きな生成済みドキュメント、ローカル設定のシークレット、またはビルドキャッシュが含まれている。
チェックリスト
- 対応環境が明記されている。
- パッケージはESMを優先し、できれば純粋なESMになっている。
-
package.jsonに"type": "module"がある。 - 公開エントリーポイントが
exportsで宣言されている。 - 宣言されていないディープインポートに誤って依存していない。
- Rslibの出力、型宣言、
exports、filesの内容が一致している。 - TypeScriptのstrictモードが有効になっている。
- 型宣言が出力され、検証されている。
- ランタイム依存関係に妥当な理由があり、数も少ない。
- ホスト側のフレームワーク/ツールチェーンはpeerになっている。
- ビルド/テスト/型チェック/ドキュメント用ツールは開発依存関係になっている。
-
sideEffectsの設定が正確である。 -
npm pack --dry-runの結果を確認している。 -
publintに合格している。 - 型宣言を同梱する場合、Are The Types Wrongのチェックに合格している。
- ビルド済みESMのスモークテストに合格している。
- README.mdが存在する。
- AGENTS.mdが存在する。
- 利用可能な場合、リリースフローでSemVer、変更履歴、provenance/信頼できる公開機能を使用している。
ドキュメント
- 最新のRslibドキュメントについては、https://rslib.rs/llms.txt を参照してください。
- CommonJSの利用者向けにESMを配布する方法:https://nodejs.github.io/package-examples/04-cjs-esm-interop/shipping-esm-for-cjs/
コメント
Markdown 対応