ネイティブプラグインは、ホストプロジェクトにインストールされ、astro.config.mjs に登録される npm パッケージです。パッケージには、ディスクリプターと createPlugin() を提供する、ビルド済みのサーバーエントリが必要です。React や Astro のコンポーネントも同梱する場合は、ホストが適切な環境向けにコンパイルできるよう、それらを別々のソースエントリポイントとしてエクスポートしてください。
パッケージレイアウト
次のレイアウトは、サーバーランタイムを、ブラウザおよび Astro のソースから分離したものです。
plugin-activity/
├── src/
│ ├── index.ts
│ ├── admin/
│ │ ├── index.tsx
│ │ └── ActivityPage.tsx
│ └── astro/
│ ├── index.ts
│ └── ActivityBlock.astro
├── dist/
│ ├── index.mjs
│ └── index.d.mts
├── package.json
├── tsconfig.json
└── README.md
dist/ は生成されるディレクトリです。ホストの Vite と Astro のビルドがこれらのエントリポイントを処理する必要があるため、公開する tarball には src/admin/ と src/astro/ を含めたままにしてください。
パッケージのエクスポート
次の package.json は、サーバーエントリをビルドし、3 つのエントリポイントすべてを公開します。
{
"name": "@example/plugin-activity",
"version": "0.1.0",
"type": "module",
"main": "./dist/index.mjs",
"exports": {
".": {
"types": "./dist/index.d.mts",
"import": "./dist/index.mjs"
},
"./admin": "./src/admin/index.tsx",
"./astro": "./src/astro/index.ts"
},
"files": ["dist", "src/admin", "src/astro"],
"scripts": {
"build": "tsdown src/index.ts --format esm --dts --clean",
"dev": "tsdown src/index.ts --format esm --dts --watch",
"typecheck": "tsc --noEmit",
"prepublishOnly": "pnpm typecheck && pnpm build"
},
"peerDependencies": {
"@cloudflare/kumo": "*",
"@emdash-cms/admin": "*",
"@lingui/core": "*",
"@lingui/react": "*",
"@tanstack/react-query": "*",
"astro": ">=6.0.0-beta.0",
"emdash": "*",
"react": "^18.0.0 || ^19.0.0"
},
"devDependencies": {
"@types/react": "^19.0.0",
"tsdown": "^0.20.0",
"typescript": "^5.9.0"
},
"keywords": ["emdash", "emdash-plugin"],
"license": "MIT"
}
プラグインに信頼された React UI がない場合は、./admin、src/admin、および管理画面専用の peer 依存関係を削除してください。Portable Text レンダラーがない場合は、./astro、src/astro、および astro の peer を削除してください。エクスポートするソースエントリポイントがインポートする、ホストが所有するライブラリごとに peer 依存関係を追加してください。これにより、管理画面のバンドルに 2 つ目の React、Kumo、Lingui、React Query のインスタンスが混入するのを防げます。
エントリポイントごとに、利用する側が異なります。
| エクスポート | 必要になる条件 | 利用する側 |
|---|---|---|
. | 常に必要 | Astro の設定がディスクリプターファクトリーをインポートし、EmDash が実行時に名前付きの createPlugin() をインポートします。 |
./admin | adminEntry を設定した場合 | ホストのブラウザビルドが、React コンポーネントのマップをインポートします。 |
./astro | componentsEntry を設定した場合 | ホストの Astro ビルドが blockComponents をインポートします。 |
ディスクリプターとランタイムのモジュール指定子は、これらのエクスポートと一致していなければなりません。
export function activityPlugin(): PluginDescriptor {
return {
id: "plugin-activity",
version: "0.1.0",
format: "native",
entrypoint: "@example/plugin-activity",
adminEntry: "@example/plugin-activity/admin",
componentsEntry: "@example/plugin-activity/astro",
};
}
export function createPlugin() {
return definePlugin({
id: "plugin-activity",
version: "0.1.0",
admin: {
entry: "@example/plugin-activity/admin",
},
});
}
npm パッケージのバージョン、ディスクリプターのバージョン、definePlugin() のバージョンは同期させてください。サイト管理者に表示されるバージョンは、プラグイン定義から取得されるもので、package.json から自動的に取得されるわけではありません。
プラグインの識別とバージョン
definePlugin() は、小文字、数字、ハイフンで構成されるスコープなしの ID、または @scope/name 形式のスコープ付き ID のいずれかを受け付けます。この ID は /_emdash/api/plugins/<plugin-id>/<route> の 1 つのパスセグメントにもなるため、サイト用プラグインにはスコープなしの kebab-case の ID を使用してください。
次の値は、受け付けられる形式と、プラグイン ID と npm パッケージ名を分けて付ける場合の推奨例を示しています。
id: "plugin-activity"; // Recommended: valid in plugin route URLs
id: "@example/plugin-activity"; // Accepted by definePlugin(), but not one URL segment
entrypoint: "@example/plugin-activity"; // The npm package may stay scoped
バージョンは、セマンティックな major.minor.patch の並びで始まる必要があります。ディスクリプターとランタイムの両方で、完全なセマンティックバージョンを使用してください。
version: "1.0.0"; // Valid
version: "1.2.3-beta.1"; // Valid prerelease
version: "1.0"; // Invalid: missing patch version
TypeScript 構成
次の tsconfig.json は、React と Astro のソースを含むネイティブプラグインに対応しています。
{
"compilerOptions": {
"target": "ES2022",
"module": "preserve",
"moduleResolution": "bundler",
"strict": true,
"declaration": true,
"outDir": "./dist",
"rootDir": "./src",
"jsx": "react-jsx",
"types": ["astro/client"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
パッケージ化の前に、ソースエントリポイントに対して pnpm typecheck を実行してください。build スクリプトがコンパイルするのは src/index.ts だけです。エクスポートされた管理画面と Astro のソースは、ホストがパッケージを利用する際にコンパイルします。
パッケージを検査する
公開する前に、tarball の内容そのものをテストします。以下のコマンドは、プラグインのディレクトリと同じ階層に、使い捨てのサイト my-emdash-site があることを前提としています。
-
パッケージをビルドして型チェックします。
pnpm typecheck pnpm build -
npm の tarball を作成し、npm が出力するファイル一覧を確認します。
npm packサンプルのパッケージでは、npm は
example-plugin-activity-0.1.0.tgzを作成します。 -
出力に、
dist/index.mjs、dist/index.d.mts、およびエクスポートされた./adminと./astroのモジュールから到達できるすべてのソースファイルが含まれていることを確認します。 -
作成した tarball を、使い捨ての EmDash サイトにインストールします。
cd ../my-emdash-site pnpm add ../plugin-activity/example-plugin-activity-0.1.0.tgz -
パッケージを作成して登録するに従い、使い捨てサイトの
astro.config.mjsでディスクリプターファクトリーをインポートして登録します。そのうえで、ホストサイトをビルドします。pnpm buildプラグインのすべての管理画面を開き、提供されているすべての Portable Text ブロックをレンダリングします。ビルドの前に登録しておくと、Astro は tarball の
./adminと./astroのエクスポートを解決します。サーバーのみを対象としたパッケージのテストでは、ブラウザ用ソースや.astroソースファイルの欠落を検出できません。
README の内容
運用担当者が、ソースを読まなくてもパッケージをインストールして評価できるだけの情報を提供してください。次の内容を含めます。
- 1 文での説明と、サポートする EmDash のバージョン
- インストールコマンドと、
astro.config.mjsへの完全な登録方法 - ネイティブの信頼境界と、プラグインがネイティブ実行を必要とする理由
- 宣言したすべての capability と許可するホスト、およびそれを使う機能
- 設定とそのデフォルト値
- body-end フラグメント用の
EmDashBodyEndなど、必要なレイアウトコンポーネント - 運用担当者の対応が必要な変更に関するアップグレード手順
capability の宣言を分離境界として説明しないでください。capability の宣言は ctx API を制限するだけで、ネイティブコードは、ホストプロセスで利用できるインポート、環境変数、直接のネットワーク呼び出しを引き続き使用できます。
npm に公開する
tarball のテストに合格したら、公開します。
npm publish --access public
スコープ付きパッケージの最初の公開リリースには --access public が必要です。以降のリリースではセマンティックバージョニングを使用してください。コンストラクターのオプション、保存データ、必要なホスト側の変更、パッケージのエクスポート、プラグインの信頼要件に対する変更は、互換性に関する判断として扱ってください。アップグレードに新しい capability や許可ホストが必要な場合は、ネイティブのインストールには capability の同意プロンプトがなくても、リリースノートで明記してください。
npm からインストールする
運用担当者は、公開されたパッケージを EmDash サイトにインストールします。
pnpm add @example/plugin-activity
続いて、パッケージを作成して登録するに示すとおり、astro.config.mjs でそのディスクリプターファクトリーをインポートして登録します。依存関係をインストールするだけではプラグインは有効になりません。Astro の設定を変更してサイトをデプロイすることで、インストールが完了します。
ホストサイトに対して開発する
プラグインをウォッチモードでビルドします。
pnpm dev
ホストサイトから、ローカルのディレクトリをインストールします。
pnpm add ../plugin-activity
astro.config.mjs にプラグインのディスクリプターファクトリーを登録してから、ホストの開発サーバーを起動します。ディスクリプターのメタデータやパッケージのエクスポートを変更した後は、サーバーを再起動してください。お使いの環境で、パッケージマネージャーのファイル依存関係がリンクではなくファイルをコピーする場合は、再ビルドの後にもう一度インストールしてください。ワークスペース依存関係や pnpm link を使うと、開発中もローカルのパッケージが接続されたままになります。
レジストリの境界
ネイティブパッケージは、EmDash レジストリに公開できません。レジストリのプラグインは、サンドボックスのパッケージ形式、署名付きのリリースワークフロー、インストール時の同意フローを使用します。プラグインが React の管理画面コード、Astro レンダラー、信頼されたフラグメント、その他のインプロセス依存関係を必要としなくなった場合は、レジストリ経由で公開する前に、サンドボックス形式に変換してください。