I plugin EmDash usano uno di due formati: sandboxed o native. Scegli il formato prima di scrivere il plugin perché la forma di authoring, il percorso di installazione e il confine di fiducia differiscono.
Scegli un plugin sandboxed a meno che il plugin non richieda un’integrazione solo native. I plugin sandboxed possono essere pubblicati nel registry e installati dall’UI di amministrazione. Un plugin native è un pacchetto npm che un operatore del sito installa nel progetto e aggiunge a astro.config.mjs prima di ridistribuire.
A colpo d’occhio
| Sandboxed | Native | |
|---|---|---|
| Authoring shape | emdash-plugin.jsonc + src/plugin.ts | definePlugin() descriptor |
| Install method | One-click from the admin registry | npm install + edit astro.config |
| Runs in | An isolated runtime provided by a sandbox runner | Same process as your Astro site |
Capability-gated ctx APIs | Enforced by the sandbox bridge | Gated by PluginContext, but not a security boundary |
| Resource limits | Runner limits for CPU, subrequests, and wall time; platform memory ceiling | No per-plugin limits |
| Network access | ctx.http, restricted to declared access | ctx.http follows declarations; native code can also call fetch() |
Direct fetch() / process.env | Blocked by the runner | Possible (plugin code shares the runtime) |
| Distribution | Signed release in the plugin registry | npm package |
| Admin UI | Block Kit (JSON-described) routes | React components, or Block Kit |
| Settings UI | Block Kit page + ctx.settings | admin.settingsSchema (auto-form) or Block Kit |
| Portable Text rendering components | Not available | componentsEntry provides Astro components |
| Page metadata contributions | page:metadata hook — meta/property tags, allowlisted <link> rels, JSON-LD | page:metadata hook (same surface) |
| Page fragment injection | Not available — meta/JSON-LD only via page:metadata | page:fragments hook — inline scripts, external scripts, raw HTML |
| Constructor options | None — read settings from KV at runtime | options on the descriptor |
Costi di un plugin native
I plugin native hanno un modello di installazione e fiducia diverso:
- Installazione a livello di progetto. Ogni sito deve installare il tuo pacchetto npm, modificare
astro.config.mjse ridistribuire. - Nessun isolamento. Un bug nel tuo plugin può far crashare il processo host o consumare il suo budget CPU. Un rejection non gestito in un hook può abbattere anche la richiesta circostante.
- Onere di fiducia sull’utente. I plugin native hanno lo stesso accesso del sito host. Le dichiarazioni di capability da sole non possono mostrare tutto ciò che il loro codice può fare.
Se il tuo plugin può fare il suo lavoro nella sandbox, dovrebbe farlo.
Quando passare a native
Scegli native per funzionalità che richiedono integrazione in build-time con il sito host:
-
Pagine o widget di amministrazione React personalizzati. I plugin sandboxed descrivono la loro UI di amministrazione con Block Kit — uno schema JSON che l’admin renderizza per conto del plugin. Se ti serve React completo (hook personalizzati, componenti di terze parti, stato complesso), ti serve native.
-
Tipi di blocco Portable Text personalizzati. La loro configurazione di editing e i componenti di rendering Astro sono caricati dal pacchetto npm installato. Solo i plugin native possono fornire quella superficie in build-time.
-
Iniettare HTML grezzo, script o fogli di stile nelle pagine pubbliche. L’hook
page:fragmentsinvia codice di prima parte ai browser dei visitatori — fuori da qualsiasi confine di sandbox. È riservato ai plugin native. I plugin sandboxed possono comunque contribuire alle pagine pubbliche tramite l’hookpage:metadata, che copre molti casi d’uso reali:- tag
meta(name+content) — descrizioni SEO, direttive robots, Twitter cards - tag
property— OpenGraph e altri meta basati su property - tag
linkcon una allowlist di rel bloccata per sicurezza (canonical,alternate,author,license,nlweb,site.standard.document) —stylesheet,prefetche rel simili di caricamento risorse sono deliberatamente non consentiti - grafi JSON-LD
Se la tua esigenza di «iniezione di pagina» è dati strutturati o metadati SEO, resta sandboxed e usa
page:metadata. Se ti serve davvero inviare JavaScript o HTML nel browser del visitatore, quello è il caso per passare a native. - tag
Se nessuna di queste funzionalità si applica, usa il formato sandboxed.
Runner di sandbox e supporto delle piattaforme
La sandbox stessa è pluggable. EmDash espone un’opzione di configurazione sandboxRunner e il runner decide come isolare il codice del plugin — non c’è nulla di specifico di Cloudflare nel formato del plugin stesso.
Con EmDash vengono forniti due runner: sandbox() da @emdash-cms/cloudflare, che esegue ogni plugin come Dynamic Worker tramite il Worker Loader di Cloudflare, e @emdash-cms/sandbox-workerd/sandbox, che esegue i plugin in un processo figlio workerd su Node.js. Plugin Sandbox copre la configurazione di ciascun runner, i limiti di risorse che applica e le differenze tra i due.
Se non è configurato alcun runner, i plugin elencati in sandboxed: [] non vengono caricati. Se il runner configurato non è disponibile sulla piattaforma corrente, non vengono caricati nemmeno loro, e EmDash registra un avviso all’avvio.
Se vuoi che un plugin sandboxed venga eseguito su una piattaforma senza runner di sandbox, spostalo da sandboxed: [] nell’array plugins: [] — verrà eseguito in-process. Le dichiarazioni di capability sono comunque rispettate (la stessa factory PluginContext limita ctx.content, ctx.http e simili), ma non c’è confine di isolamento, né limiti di risorse, e un plugin difettoso o dannoso può chiamare fetch() direttamente, leggere variabili d’ambiente o bloccare l’event loop. Senza un runner di sandbox attivo, tratta ogni plugin come un plugin native a fini di fiducia.