原生外掛是安裝在宿主專案中並在 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/ 是產生的。請在已發佈的 tarball 中保留 src/admin/ 與 src/astro/,因為宿主的 Vite 與 Astro 建置必須處理這些進入點。
套件匯出
以下 package.json 建置伺服器進入點並發佈全部三個進入點:
{
"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 以及僅管理端的 peerDependencies。當沒有 Portable Text 渲染器時,移除 ./astro、src/astro 與 astro peer。為每個匯出的來源進入點匯入的宿主擁有函式庫新增 peerDependency;這可防止第二個 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。對網站外掛使用無作用域、kebab-case 的 ID,因為 ID 也佔用 /_emdash/api/plugins/<plugin-id>/<route> 中的一個路徑區段。
以下值顯示可接受形式以及外掛 ID 與 npm 套件名稱之間的建議分離:
id: "plugin-activity"; // 建議:在外掛路由 URL 中有效
id: "@example/plugin-activity"; // definePlugin() 接受,但不是一個 URL 區段
entrypoint: "@example/plugin-activity"; // npm 套件可以保持作用域
版本必須以語意化 major.minor.patch 序列開頭。對描述子與執行階段都使用完整語意版本:
version: "1.0.0"; // 有效
version: "1.2.3-beta.1"; // 有效的預發佈
version: "1.0"; // 無效:缺少修補版本
TypeScript 設定
原生鷹架會建立合適的 tsconfig.json。若外掛在鷹架之後新增 React 與 Astro 原始碼,請包含兩種 JSX 環境:
{
"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 內容
為營運者提供足夠資訊,使其無需閱讀原始碼即可安裝並評估套件。包括:
- 一句話描述與支援的 EmDash 版本
- 安裝命令與完整的
astro.config.mjs註冊 - 原生信任邊界以及外掛為何需要原生執行
- 每個已宣告能力與允許的主機,以及使用它的功能
- 設定及其預設值
- 必要的版面元件,例如用於 body-end 片段的
EmDashBodyEnd - 需要營運者操作的變更的升級步驟
不要將能力宣告描述為隔離邊界。它們對 ctx API 設門,但原生程式碼仍可使用宿主行程可用的匯入、環境變數與直接網路呼叫。
發佈到 npm
tarball 測試通過後發佈:
npm publish --access public
作用域套件的首次公開發佈需要 --access public。後續發佈使用語意化版本。將建構函式選項、已存資料、必要的宿主變更、套件匯出或外掛信任要求的變更視為相容性決策。若升級需要新能力或允許的主機,即使原生安裝沒有能力同意提示,也請在發佈說明中指出。
從 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 渲染器、受信任片段或其他行程內依賴,請在透過登錄庫發佈前 轉換為沙箱格式。