原生外掛是 EmDash 匯入到與 Astro 網站同一行程中的 npm 套件。本教學建立一個記錄內容儲存的外掛,將其安裝到網站,並在 astro.config.mjs 中註冊。
當外掛需要行程內功能(如 React 管理元件、Astro 渲染元件或受信任的頁面片段)時,使用原生格式。若掛鉤、路由、儲存與 Block Kit 已涵蓋該功能,請從沙箱外掛開始。選擇外掛格式 比較了兩種格式。
先決條件
從使用 pnpm 且能執行開發伺服器的 EmDash 網站開始。網站必須已依賴 emdash,它提供下文使用的 emdash 命令。
命令將網站目錄稱為 my-emdash-site,並在其旁建立 plugin-activity。將 my-emdash-site 取代為你的網站目錄名稱。
建立並註冊套件
-
在網站旁搭建原生套件。
pnpm exec emdash plugin init --native --name @example/plugin-activity --dir ../plugin-activity命令在建立外掛 ID 時會移除 npm 作用域。套件名稱為
@example/plugin-activity,外掛 ID 為plugin-activity。 -
安裝套件依賴。
cd ../plugin-activity pnpm install -
將產生的
src/index.ts取代為內容儲存掛鉤。import { definePlugin } from "emdash"; import type { PluginDescriptor } from "emdash"; export interface ActivityPluginOptions { logUpdates?: boolean; } export function activityPlugin( options: ActivityPluginOptions = {}, ): PluginDescriptor<ActivityPluginOptions> { return { id: "plugin-activity", version: "0.1.0", format: "native", entrypoint: "@example/plugin-activity", options, }; } export function createPlugin(options: ActivityPluginOptions = {}) { return definePlugin({ id: "plugin-activity", version: "0.1.0", capabilities: ["content:read"], hooks: { "content:afterSave": async (event, ctx) => { if (!event.isNew && options.logUpdates === false) return; ctx.log.info("Content saved", { collection: event.collection, contentId: event.content.id, isNew: event.isNew, }); }, }, }); } export default createPlugin;content:afterSave需要content:read能力。缺少該能力時 EmDash 會跳過該掛鉤。 -
建置套件。
pnpm build -
將本機套件安裝到網站。
cd ../my-emdash-site pnpm add ../plugin-activity -
在 EmDash 整合中註冊描述子工廠。
import { defineConfig } from "astro/config"; import emdash from "emdash/astro"; import { activityPlugin } from "@example/plugin-activity"; export default defineConfig({ integrations: [ emdash({ plugins: [activityPlugin({ logUpdates: true })], }), ], });原生描述子屬於
plugins,不屬於sandboxed。EmDash 會拒絕sandboxed陣列中的原生描述子。 -
啟動網站並在管理面板中儲存一筆項目。
pnpm dev伺服器日誌包含帶有集合、內容 ID 以及項目是否新建的
Content saved。
描述子與執行階段邊界
套件匯出有兩項工作。EmDash 在不同階段使用各自:
- 描述子工廠
activityPlugin()在 Astro 評估其設定時執行。它回傳可序列化的建置時中繼資料:id、version、format、entrypoint與options。React 與 Astro 進入點也屬於此描述子。 - 具名
createPlugin()匯出在 EmDash 初始化時執行。EmDash 從entrypoint匯入它,傳入序列化的options,並期望從definePlugin()得到已解析的外掛。
具名 createPlugin 匯出是必要的。預設匯出可能對套件使用者有用,但 EmDash 的原生載入器依名稱匯入 createPlugin。
在描述子與 definePlugin() 中保持 id 與 version 相同。使用無作用域、kebab-case 的外掛 ID,如 plugin-activity;將 npm 作用域保留在套件名稱與 entrypoint 中。這樣 ID 可作為 API 路由 URL 中的單一外掛區段使用。
外掛識別與版本 列出可接受的 ID 與版本形式。
執行階段行為屬於 definePlugin():
capabilities與allowedHostsstoragehooks與routesadmin設定、頁面、小工具與 Portable Text 宣告
描述子攜帶 Astro 必須在建置時匯入或暴露的靜態項目。專題指南說明哪些管理欄位需要匹配的描述子與執行階段宣告。
原生路由處理常式
原生路由處理常式接收一個 RouteContext。它將已驗證輸入與請求資料與常規 PluginContext 合併:
routes: {
status: {
permission: "plugins:read",
handler: async (ctx) => ({
pluginId: ctx.plugin.id,
callerId: ctx.user?.id ?? null,
}),
},
},
等效的沙箱處理常式以兩個參數接收 (routeCtx, ctx)。身分驗證、權限、輸入 schema 與路由 URL 在其他方面遵循共用的 API 路由 約定。
當原生路由宣告 request.body 時,用 definePluginRoute() 包裝它;該輔助函式從 body 模式推斷
ctx.input。帶 response: "raw" 的原生路由回傳 pluginResponse()。
從 emdash 匯入這兩個輔助函式。共用 API 路由指南列出 body 模式、限制、回應策略與相容性預設值。
新增另一個表面
- React 管理頁面與小工具 涵蓋設定、自訂頁面、儀表板小工具、編輯器面板與清單欄。
- Portable Text 渲染元件 為外掛區塊註冊 Astro 元件。
- 頁面片段 向公開頁面新增受信任的腳本或 HTML。
- 分發原生外掛 為 npm 打包建置與來源進入點。