Os plugins EmDash são fornecidos em um dos dois formatos: sandboxed ou native. A escolha afeta como o plugin é instalado, que aplicação ele recebe em tempo de execução e quais recursos estão disponíveis.
O padrão é sandboxed. Plugins sandboxed podem ser publicados no marketplace e instalados da interface de administração com um clique. Plugins nativos requerem uma mudança de código, um npm install e um novo deploy em cada site que os deseja. Sandboxed é o que os usuários finais querem.
Escolha nativo apenas quando você precisar de um recurso que o sandbox não pode fornecer.
De relance
| Sandboxed | Native | |
|---|---|---|
| Forma de autoria | emdash-plugin.jsonc + src/plugin.ts | Descritor definePlugin() |
| Método de instalação | Um clique do marketplace de administração | npm install + editar astro.config |
| Executa em | Um runtime isolado fornecido por um sandbox runner | Mesmo processo que seu site Astro |
| Capacidades | Aplicadas pela ponte do sandbox | Aplicadas em processo pela mesma ponte |
| Limites de recursos | Aplicados pelo runner — tipicamente CPU, subrequests, wall-time, memória | Nenhum |
| Acesso à rede | Apenas ctx.http, restrito a allowedHosts | Apenas ctx.http, restrito a allowedHosts |
fetch() / process.env diretos | Bloqueados pelo runner | Possível (código do plugin compartilha o runtime) |
| Distribuição | Bundle .tar.gz no marketplace | Pacote npm |
| Interface de administração | Rotas Block Kit (descritas em JSON) | Componentes React, ou Block Kit |
| Interface de configurações | Página Block Kit + leituras KV | admin.settingsSchema (formulário automático) ou Block Kit |
| Componentes de renderização Portable Text | Não disponível | componentsEntry fornece componentes Astro |
| Contribuições de metadados de página | Hook page:metadata — tags meta/property, rels <link> permitidos, JSON-LD | Hook page:metadata (mesma superfície) |
| Injeção de fragmentos de página | Não disponível — apenas meta/JSON-LD via page:metadata | Hook page:fragments — scripts inline, scripts externos, HTML bruto |
| Opções do construtor | Nenhuma — ler configurações do KV em runtime | options no descritor |
O que você perde ao escolher nativo
Plugins nativos parecem uma versão mais poderosa da mesma coisa, e eles são — mas o custo é alto:
- Sem marketplace. Cada site tem que instalar seu pacote npm, editar
astro.config.mjse reimplantar. - Sem isolamento. Um bug no seu plugin pode travar o processo host ou queimar seu orçamento de CPU. Uma rejeição não tratada em um hook pode derrubar a requisição ao redor com ela.
- Carga de confiança no usuário. Plugins nativos têm o mesmo acesso que o site host. Usuários finais não podem auditá-los apenas através de declarações de capacidades.
Se seu plugin pode fazer seu trabalho no sandbox, ele deveria fazê-lo.
Quando escolher nativo
Existem três razões para escolher nativo, e todas são sobre recursos que precisam de integração em tempo de compilação com o site host:
-
Páginas ou widgets de administração React personalizados. Plugins sandboxed descrevem sua interface de administração com Block Kit — um esquema JSON que o administrador renderiza em nome do plugin. Se você precisa de React completo (hooks personalizados, componentes de terceiros, estado complexo), você precisa de nativo.
-
Componentes Astro para renderizar blocos Portable Text no site público. Um plugin sandboxed pode declarar um tipo de bloco personalizado, mas os componentes Astro que o renderizam no site público devem ser carregados em tempo de compilação do npm. Apenas plugins nativos podem fornecer um
componentsEntry. -
Injetar HTML bruto, scripts ou folhas de estilo em páginas públicas. O hook
page:fragmentsenvia código first-party aos navegadores dos visitantes — fora de qualquer limite de sandbox. É restrito a plugins nativos. Plugins sandboxed ainda podem contribuir para páginas públicas através do hookpage:metadata, que cobre muitos casos de uso reais:- Tags
meta(name+content) — descrições SEO, diretivas de robôs, cards do Twitter - Tags
property— OpenGraph e outros meta baseados em propriedades - Tags
linkcom uma lista de permissões rel bloqueada por segurança (canonical,alternate,author,license,nlweb,site.standard.document) —stylesheet,prefetche rels similares de carregamento de recursos não são deliberadamente permitidos - Grafos JSON-LD
Se sua necessidade de “injeção de página” for dados estruturados ou metadados SEO, fique sandboxed e use
page:metadata. Se você realmente precisa enviar JavaScript ou HTML para o navegador do visitante, esse é o caso para escolher nativo. - Tags
Se você não tem certeza, escolha sandboxed. Você sempre pode migrar para nativo mais tarde — mas o reverso é mais difícil, porque recursos exclusivos de nativo não têm equivalente em sandbox.
Sandbox runners e suporte de plataforma
O sandbox em si é plugável. EmDash expõe uma opção de configuração sandboxRunner e o runner decide como o código do plugin é isolado — não há nada específico do Cloudflare no formato do plugin em si.
O runner que a maioria dos sites usa hoje é sandbox() de @emdash-cms/cloudflare, que usa Dynamic Worker Loader do Cloudflare Workers. O Worker Loader armazena em cache o isolado V8 por id de plugin, então o custo de inicialização a frio do isolado é pago apenas uma vez; o runner constrói um stub de worker fresco e bindings de ponte em cada invocação, já que stubs e bindings estão vinculados ao contexto de I/O da requisição chamadora. Runners para outras plataformas (Node.js via workerd, e potencialmente Deno) estão em desenvolvimento.
Se nenhum runner estiver configurado, ou se o runner configurado reportar como indisponível na plataforma atual, plugins listados sob sandboxed: [] são ignorados na inicialização com um log de nível de debug.
Se você quiser que um plugin sandboxed execute em uma plataforma sem um sandbox runner, mova-o de sandboxed: [] para o array plugins: [] — ele executará em processo. Declarações de capacidades ainda são respeitadas (a mesma factory PluginContext controla ctx.content, ctx.http e amigos), mas não há limite de isolamento, sem limites de recursos, e um plugin com bug ou malicioso pode chamar fetch() diretamente, ler variáveis de ambiente ou bloquear o loop de eventos. Sem um sandbox runner ativo, trate cada plugin como um plugin nativo para fins de confiança.