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 braucht einen gebauten Server-Entry für seinen Descriptor und createPlugin(). Wenn es auch React- oder Astro-Komponenten ausliefert, exportieren Sie diese als separate Source-Entrypoints, damit der Host sie für die richtige Umgebung kompilieren kann.

Paketlayout

Das folgende Layout trennt die Server-Runtime von Browser- und Astro-Source:

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 Entrypoints verarbeiten muss.

Paketexporte

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

{
	"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 admin-only Peer-Dependencies, 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 eine Peer-Dependency für jede host-eigene Bibliothek hinzu, die ein exportierter Source-Entrypoint importiert; das verhindert, dass eine zweite React-, Kumo-, Lingui- oder React-Query-Instanz in das Admin-Bundle gelangt.

Die Entrypoints haben unterschiedliche Konsumenten:

ExportErforderlich wennKonsument
.ImmerDie Astro-Konfiguration importiert die Descriptor-Factory; EmDash importiert das benannte createPlugin() zur Laufzeit.
./adminadminEntry ist gesetztDer Browser-Build des Hosts importiert die React-Komponenten-Maps.
./astrocomponentsEntry ist gesetztDer Astro-Build des Hosts importiert blockComponents.

Die Modul-Specifier im Descriptor und in der Runtime müssen diesen Exporten entsprechen:

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 Descriptor-Version und die definePlugin()-Version synchron. Die einem Site-Administrator angezeigte Version kommt aus der Plugin-Definition, nicht automatisch aus package.json.

Plugin-Identität und Version

definePlugin() akzeptiert entweder eine unscopierte ID mit Kleinbuchstaben, Ziffern und Bindestrichen oder eine scopierte ID in der Form @scope/name. Verwenden Sie für ein Site-Plugin eine unscopierte kebab-case-ID, weil 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"; // Empfohlen: gültig in Plugin-Routen-URLs
id: "@example/plugin-activity"; // Von definePlugin() akzeptiert, aber nicht ein URL-Segment

entrypoint: "@example/plugin-activity"; // Das npm-Paket darf scopiert bleiben

Versionen müssen mit einer semantischen major.minor.patch-Sequenz beginnen. Verwenden Sie eine vollständige semantische Version für Descriptor und Runtime:

version: "1.0.0"; // Gültig
version: "1.2.3-beta.1"; // Gültige Prerelease
version: "1.0"; // Ungültig: fehlende Patch-Version

TypeScript-Konfiguration

Der native Scaffold erzeugt eine passende tsconfig.json. Wenn das Plugin nach dem Scaffolden React- und Astro-Source hinzufügt, schließen Sie beide JSX-Umgebungen ein:

{
	"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 pnpm typecheck gegen die Source-Entrypoints aus, bevor Sie paketieren. Das build-Skript kompiliert nur src/index.ts; der Host kompiliert die exportierte Admin- und Astro-Source, wenn er das Paket konsumiert.

Das Paket prüfen

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

  1. Bauen und typechecken Sie das Paket.

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

    npm pack

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

  3. Bestätigen Sie, dass die Ausgabe dist/index.mjs, dist/index.d.mts und jede Source-Datei enthält, die von den exportierten Modulen ./admin und ./astro 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 Descriptor-Factory in der astro.config.mjs der Wegwerf-Site gemäß Paket erstellen und registrieren. Bauen Sie dann die Host-Site.

    pnpm build

    Öffnen Sie jede Plugin-Admin-Oberfläche und rendern Sie jeden beigetragenen Portable-Text-Block. Das Registrieren vor dem Build lässt Astro die ./admin- und ./astro-Exporte des Tarballs auflösen; ein server-only Pakettest kann eine fehlende Browser- oder .astro-Source-Datei nicht fangen.

README-Inhalte

Geben Sie einem Betreiber genug Informationen, um das Paket zu installieren und zu bewerten, ohne seinen Quellcode zu lesen. Enthalten Sie:

  • eine Ein-Satz-Beschreibung und die unterstützte EmDash-Version
  • den Installationsbefehl und die vollständige astro.config.mjs-Registrierung
  • die native Vertrauensgrenze und warum das Plugin native Ausführung braucht
  • jede deklarierte Capability und jeden erlaubten Host, mit dem Feature, das sie nutzt
  • Einstellungen und ihre Defaults
  • erforderliche Layout-Komponenten, etwa EmDashBodyEnd für ein body-end-Fragment
  • Upgrade-Schritte für Änderungen, die eine Betreiberaktion erfordern

Beschreiben Sie Capability-Deklarationen nicht als Isolationsgrenze. Sie gated 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 hat:

npm publish --access public

Die erste öffentliche Veröffentlichung eines scopierten Pakets braucht --access public. Verwenden Sie semantische Versionierung für spätere Releases. Behandeln Sie Änderungen an Constructor-Optionen, gespeicherten Daten, erforderlichen Host-Änderungen, Paketexporten oder den Vertrauensanforderungen des Plugins als Kompatibilitätsentscheidungen. Wenn ein Upgrade eine neue Capability oder einen erlaubten Host braucht, erwähnen Sie das in den Release Notes, auch wenn native Installationen keinen Capability-Consent-Prompt haben.

Von npm installieren

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

pnpm add @example/plugin-activity

Importieren und registrieren Sie dann seine Descriptor-Factory in astro.config.mjs wie in Paket erstellen und registrieren gezeigt. Die Abhängigkeit allein zu installieren aktiviert das Plugin nicht; das Ändern der Astro-Konfiguration und das Deployen 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 von der Host-Site:

pnpm add ../plugin-activity

Registrieren Sie die Descriptor-Factory des Plugins in astro.config.mjs und starten Sie dann den Host-Entwicklungsserver. Starten Sie den Server neu, nachdem Sie Descriptor-Metadaten oder Paketexporte geändert haben. Wenn eine Paketmanager-Dateiabhängigkeit in Ihrem Setup Dateien kopiert statt zu verlinken, installieren Sie sie nach dem Rebuild neu; 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 nutzen das sandboxed Paketformat, den signierten Release-Workflow und den Installations-Consent-Flow. Wenn das Plugin keine React-Admin-Code, Astro-Renderer, vertrauenswürdige Fragmente oder eine andere In-Process-Abhängigkeit mehr braucht, konvertieren Sie es in das sandboxed Format, bevor Sie über die Registry veröffentlichen.