Los plugins de EmDash se distribuyen en uno de dos formatos: sandboxed o native. La elección afecta cómo se instala el plugin, qué aplicación obtiene en tiempo de ejecución y qué características están disponibles.
Por defecto, use sandboxed. Los plugins sandboxed se pueden publicar en el marketplace e instalarse desde la interfaz de administración con un solo clic. Los plugins nativos requieren un cambio de código, un npm install y un redespliegue en cada sitio que los quiera usar. Sandboxed es lo que los usuarios finales desean.
Elija native solo cuando necesite una característica que el sandbox no pueda proporcionar.
De un vistazo
| Sandboxed | Native | |
|---|---|---|
Campo format en el descriptor | "standard" | "native" |
| Método de instalación | Un clic desde el marketplace de administración | npm install + editar astro.config |
| Se ejecuta en | Un runtime aislado proporcionado por un sandbox runner | El mismo proceso que su sitio Astro |
| Capacidades | Aplicadas por el puente del sandbox | Aplicadas en proceso por el mismo puente |
| Límites de recursos | Aplicados por el runner — típicamente CPU, subrequests, tiempo de ejecución, memoria | Ninguno |
| Acceso a red | Solo ctx.http, restringido a allowedHosts | Solo ctx.http, restringido a allowedHosts |
fetch() / process.env directo | Bloqueado por el runner | Posible (el código del plugin comparte el runtime) |
| Distribución | Bundle .tar.gz en el marketplace | Paquete npm |
| Interfaz de administración | Rutas Block Kit (descritas en JSON) | Componentes React o Block Kit |
| Interfaz de configuración | Página Block Kit + lecturas KV | admin.settingsSchema (formulario automático) o Block Kit |
| Componentes de renderizado Portable Text | No disponible | componentsEntry proporciona componentes Astro |
| Contribuciones de metadatos de página | Hook page:metadata — etiquetas meta/property, rels <link> permitidos, JSON-LD | Hook page:metadata (misma superficie) |
| Inyección de fragmentos de página | No disponible — solo meta/JSON-LD vía page:metadata | Hook page:fragments — scripts inline, scripts externos, HTML crudo |
| Opciones del constructor | Ninguna — leer configuración de KV en tiempo de ejecución | options en el descriptor |
Lo que se sacrifica al elegir native
Los plugins nativos parecen una versión más poderosa de lo mismo, y lo son — pero el costo es alto:
- Sin marketplace. Cada sitio tiene que instalar su paquete npm, editar
astro.config.mjsy redesplegar. - Sin aislamiento. Un error en su plugin puede bloquear el proceso host o consumir su presupuesto de CPU. Un rechazo no manejado en un hook puede derribar la solicitud circundante con él.
- Carga de confianza en el usuario. Los plugins nativos tienen el mismo acceso que el sitio host. Los usuarios finales no pueden auditarlos solo a través de declaraciones de capacidades.
Si su plugin puede hacer su trabajo en el sandbox, debería hacerlo.
Cuándo elegir native
Hay tres razones para elegir native, y todas se tratan de características que necesitan integración en tiempo de compilación con el sitio host:
-
Páginas de administración o widgets React personalizados. Los plugins sandboxed describen su interfaz de administración con Block Kit — un esquema JSON que el administrador renderiza en nombre del plugin. Si necesita React completo (hooks personalizados, componentes de terceros, estado complejo), necesita native.
-
Componentes Astro para renderizar bloques Portable Text en el sitio público. Un plugin puede declarar un tipo de bloque personalizado con
format: "standard", pero los componentes Astro que lo renderizan en el sitio público deben cargarse en tiempo de compilación desde npm. Solo los plugins nativos pueden proporcionar uncomponentsEntry. -
Inyectar HTML crudo, scripts o hojas de estilo en páginas públicas. El hook
page:fragmentsenvía código de primera parte a los navegadores de los visitantes — fuera de cualquier límite del sandbox. Está restringido a plugins nativos. Los plugins sandboxed aún pueden contribuir a páginas públicas a través del hookpage:metadata, que cubre muchos casos de uso reales:- Etiquetas
meta(name+content) — descripciones SEO, directivas de robots, Twitter Cards - Etiquetas
property— OpenGraph y otros metadatos basados en propiedades - Etiquetas
linkcon una lista permitida de rel bloqueada por seguridad (canonical,alternate,author,license,nlweb,site.standard.document) —stylesheet,prefetchy rels similares de carga de recursos no están permitidos deliberadamente - Grafos JSON-LD
Si su necesidad de “inyección de página” es datos estructurados o metadatos SEO, manténgase en sandboxed y use
page:metadata. Si realmente necesita enviar JavaScript o HTML al navegador del visitante, ese es el caso para elegir native. - Etiquetas
Si no está seguro, elija sandboxed. Siempre puede migrar a native más adelante — pero lo contrario es más difícil, porque las características exclusivas de native no tienen equivalente en sandbox.
Sandbox runners y soporte de plataforma
El sandbox en sí es pluggable. EmDash expone una opción de configuración sandboxRunner y el runner decide cómo se aísla el código del plugin — no hay nada específico de Cloudflare en el formato del plugin en sí.
El runner que la mayoría de los sitios usan hoy es sandbox() de @emdash-cms/cloudflare, que usa el Dynamic Worker Loader de Cloudflare Workers. Worker Loader cachea el aislamiento V8 por ID de plugin, por lo que el costo de arranque en frío del aislamiento solo se paga una vez; el runner construye un worker stub fresco y bindings de puente en cada invocación, ya que los stubs y bindings están vinculados al contexto de I/O de la solicitud que llama. Los runners para otras plataformas (Node.js vía workerd y potencialmente Deno) están en desarrollo.
Si no hay un runner configurado, o si el runner configurado informa que no está disponible en la plataforma actual, los plugins listados bajo sandboxed: [] se omiten al inicio con un log de nivel debug.
Si desea que un plugin de formato estándar se ejecute en una plataforma sin un sandbox runner, muévalo de sandboxed: [] al array plugins: [] — se ejecutará en proceso. Las declaraciones de capacidades aún se respetan (la misma fábrica PluginContext restringe ctx.content, ctx.http y similares), pero no hay límite de aislamiento, no hay límites de recursos, y un plugin defectuoso o malicioso puede llamar a fetch() directamente, leer variables de entorno o bloquear el event loop. Sin un sandbox runner activo, trate cada plugin como un plugin nativo a efectos de confianza.