Native Plugins verteilen

Auf dieser Seite

Native Plugins sind npm-Pakete, die im Host-Projekt installiert und in astro.config.mjs registriert werden. Das Paket benötigt einen gebauten Server-Einstiegspunkt für seinen Deskriptor und createPlugin(). Wenn es zusätzlich React- oder Astro-Komponenten mitliefert, exportieren Sie diese als separate Quell-Einstiegspunkte, damit der Host sie für die richtige Umgebung kompilieren kann.

Paketlayout

Das folgende Layout trennt die Server-Laufzeit vom Browser- und Astro-Quellcode:

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/ wird generiert. Behalten Sie src/admin/ und src/astro/ im veröffentlichten Tarball, weil der Vite- und Astro-Build des Hosts diese Einstiegspunkte verarbeiten muss.

Paketexporte

Die folgende package.json baut den Server-Einstiegspunkt und veröffentlicht alle drei Einstiegspunkte:

{
	"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"
}

Entfernen Sie ./admin, src/admin und die nur für den Admin-Bereich benötigten Peer-Abhängigkeiten, wenn das Plugin keine vertrauenswürdige React-UI hat. Entfernen Sie ./astro, src/astro und den astro-Peer, wenn es keinen Portable-Text-Renderer hat. Fügen Sie für jede vom Host bereitgestellte Bibliothek, die ein exportierter Quell-Einstiegspunkt importiert, eine Peer-Abhängigkeit hinzu; so verhindern Sie, dass eine zweite React-, Kumo-, Lingui- oder React-Query-Instanz in das Admin-Bundle gelangt.

Die Einstiegspunkte haben unterschiedliche Verbraucher:

ExportErforderlich, wennVerbraucher
.ImmerDie Astro-Konfiguration importiert die Deskriptor-Factory; EmDash importiert zur Laufzeit das benannte createPlugin().
./adminadminEntry gesetzt istDer Browser-Build des Hosts importiert die React-Komponenten-Maps.
./astrocomponentsEntry gesetzt istDer Astro-Build des Hosts importiert blockComponents.

Die Modulspezifizierer im Deskriptor und in der Laufzeit müssen zu diesen Exporten passen:

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",
		},
	});
}

Halten Sie die npm-Paketversion, die Deskriptor-Version und die Version in definePlugin() synchron. Die einem Site-Administrator angezeigte Version stammt aus der Plugin-Definition, nicht automatisch aus package.json.

Plugin-Identität und Version

definePlugin() akzeptiert entweder eine ID ohne Scope, die aus Kleinbuchstaben, Ziffern und Bindestrichen besteht, oder eine ID mit Scope in der Form @scope/name. Verwenden Sie für ein Site-Plugin eine ID ohne Scope in Kebab-Case, da die ID auch ein Pfadsegment in /_emdash/api/plugins/<plugin-id>/<route> belegt.

Die folgenden Werte zeigen die akzeptierten Formen und die empfohlene Trennung zwischen Plugin-ID und npm-Paketname:

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

Versionen müssen mit einer semantischen Folge major.minor.patch beginnen. Verwenden Sie sowohl für den Deskriptor als auch für die Laufzeit eine vollständige semantische Version:

version: "1.0.0"; // Valid
version: "1.2.3-beta.1"; // Valid prerelease
version: "1.0"; // Invalid: missing patch version

TypeScript-Konfiguration

Die folgende tsconfig.json deckt ein natives Plugin mit React- und Astro-Quellcode ab:

{
	"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"]
}

Führen Sie vor dem Paketieren pnpm typecheck für die Quell-Einstiegspunkte aus. Das build-Skript kompiliert nur src/index.ts; den exportierten Admin- und Astro-Quellcode kompiliert der Host, wenn er das Paket verwendet.

Das Paket prüfen

Testen Sie vor dem Veröffentlichen den exakten Inhalt des Tarballs. Die folgenden Befehle gehen davon aus, dass eine Wegwerf-Site namens my-emdash-site neben dem Plugin-Verzeichnis liegt.

  1. Bauen Sie das Paket und prüfen Sie die Typen.

    pnpm typecheck
    pnpm build
  2. Erstellen Sie den npm-Tarball und prüfen Sie die von npm ausgegebene Dateiliste.

    npm pack

    Für das Beispielpaket erstellt npm example-plugin-activity-0.1.0.tgz.

  3. Vergewissern Sie sich, dass die Ausgabe dist/index.mjs, dist/index.d.mts und jede Quelldatei enthält, die von den exportierten Modulen ./admin und ./astro aus erreichbar ist.

  4. Installieren Sie den erzeugten Tarball in der Wegwerf-EmDash-Site.

    cd ../my-emdash-site
    pnpm add ../plugin-activity/example-plugin-activity-0.1.0.tgz
  5. Importieren und registrieren Sie die Deskriptor-Factory in der astro.config.mjs der Wegwerf-Site, wie unter Das Paket erstellen und registrieren beschrieben. Bauen Sie anschließend die Host-Site.

    pnpm build

    Öffnen Sie jede Admin-Oberfläche des Plugins und rendern Sie jeden beigesteuerten Portable-Text-Block. Wenn Sie vor dem Build registrieren, löst Astro die Exporte ./admin und ./astro des Tarballs auf; ein reiner Server-Test des Pakets kann eine fehlende Browser- oder .astro-Quelldatei nicht erkennen.

README-Inhalte

Geben Sie einem Betreiber genug Informationen, um das Paket zu installieren und zu bewerten, ohne den Quellcode zu lesen. Nehmen Sie auf:

  • eine einsätzige Beschreibung und die unterstützte EmDash-Version
  • den Installationsbefehl und die vollständige Registrierung in astro.config.mjs
  • die native Vertrauensgrenze und warum das Plugin native Ausführung benötigt
  • jede deklarierte Capability und jeden erlaubten Host, mit der Funktion, die sie nutzt
  • Einstellungen und ihre Standardwerte
  • erforderliche Layout-Komponenten, etwa EmDashBodyEnd für ein Body-End-Fragment
  • Upgrade-Schritte für Änderungen, die ein Handeln des Betreibers erfordern

Beschreiben Sie Capability-Deklarationen nicht als Isolationsgrenze. Sie steuern den Zugriff auf ctx-APIs, aber nativer Code kann weiterhin Imports, Umgebungsvariablen und direkte Netzwerkaufrufe nutzen, die dem Host-Prozess zur Verfügung stehen.

Bei npm veröffentlichen

Veröffentlichen Sie, nachdem der Tarball-Test bestanden wurde:

npm publish --access public

Das erste öffentliche Release eines Pakets mit Scope benötigt --access public. Verwenden Sie für spätere Releases semantische Versionierung. Behandeln Sie Änderungen an Konstruktoroptionen, gespeicherten Daten, erforderlichen Host-Änderungen, Paketexporten oder den Vertrauensanforderungen des Plugins als Kompatibilitätsentscheidungen. Wenn ein Upgrade eine neue Capability oder einen neuen erlaubten Host erfordert, weisen Sie in den Release Notes darauf hin, auch wenn native Installationen keine Capability-Zustimmungsabfrage haben.

Von npm installieren

Ein Betreiber installiert das veröffentlichte Paket in der EmDash-Site:

pnpm add @example/plugin-activity

Importieren und registrieren Sie anschließend seine Deskriptor-Factory in astro.config.mjs, wie unter Das Paket erstellen und registrieren gezeigt. Die Installation der Abhängigkeit allein aktiviert das Plugin nicht; erst die Änderung der Astro-Konfiguration und das Deployment der Site schließen die Installation ab.

Gegen eine Host-Site entwickeln

Bauen Sie das Plugin im Watch-Modus:

pnpm dev

Installieren Sie das lokale Verzeichnis aus der Host-Site:

pnpm add ../plugin-activity

Registrieren Sie die Deskriptor-Factory des Plugins in astro.config.mjs und starten Sie dann den Entwicklungsserver des Hosts. Starten Sie den Server neu, nachdem Sie Deskriptor-Metadaten oder Paketexporte geändert haben. Falls eine Datei-Abhängigkeit Ihres Paketmanagers in Ihrem Setup Dateien kopiert, statt sie zu verlinken, installieren Sie sie nach dem Neubau erneut; eine Workspace-Abhängigkeit oder pnpm link hält das lokale Paket während der Entwicklung verbunden.

Registry-Grenze

Native Pakete können nicht in der EmDash-Registry veröffentlicht werden. Registry-Plugins verwenden das Sandbox-Paketformat, den signierten Release-Workflow und den Zustimmungsablauf bei der Installation. Wenn das Plugin keinen React-Admin-Code, keine Astro-Renderer, keine vertrauenswürdigen Fragmente oder andere In-Process-Abhängigkeiten mehr benötigt, wandeln Sie es in das Sandbox-Format um, bevor Sie es über die Registry veröffentlichen.