Estrategias por entorno

Un modelo de resolución y entrega, consumido de cuatro maneras: navegadores con módulos ES nativos o SystemJS, Node.js mediante BEE Node y Deno mediante su import map, con las actualizaciones de desarrollo que funcionan en todos ellos y las mediciones locales que respaldan los valores predeterminados.

  • Disponibilidad: Experimental
  • Evidencia: Ejecución registrada
  • Explicación

Un modelo

Todo origen del contrato de entrega responde las mismas dos cosas: los módulos en sus direcciones /m/…, y la resolución que indica qué dirección entrega cada especificador público, en /resolution.json y /importmap.json. Un origen es un servidor de desarrollo, un entorno de Workspace o la base de un release del CDN (/_r/<release number>).

Un entorno no necesita una entrega propia. Necesita una forma de consumir esos dos documentos: convertir un especificador simple en una dirección, obtenerla de ese origen y ejecutarla. Esa es la única parte que cambia de un entorno a otro.

Las estrategias

Entorno Cómo resuelve Qué salidas
Navegador, módulos ES nativos (predeterminado) Un import map en línea en la página; los módulos inmediatos se precargan target=browser&format=esm
Navegador, SystemJS SystemJS 6.15.1, guardado con el release como loader.js, que lee un systemjs-importmap target=browser&format=system
Node.js El adaptador resolution de BEE Node lee resolution.json de la base target=node&format=esm
Deno Deno lee importmap.json de la base de forma nativa target=node&format=esm, o salidas de navegador neutrales respecto de la plataforma mediante el mapa de navegador

Un release elige su cargador de navegador cuando se prepara (loader de la aplicación: esm o system). Node.js y Deno usan el target de backend de la aplicación, cuyas salidas y cuya resolución también guarda un release. Consulta Targets de backend.

Navegadores

Los módulos ES nativos son el predeterminado. El shell de un release incluye en línea su import map con direcciones ligadas al release y anuncia los módulos inmediatos con <link rel="modulepreload">, para que el navegador los obtenga en paralelo. Consulta ESM nativo e import maps.

SystemJS es el modo para entornos sin import maps. El release guarda SystemJS como su propio loader.js, así que ninguna página llega a un origen de terceros. Consulta SystemJS.

En ambos, las hojas de estilos se aplican de forma explícita: el documento las enlaza, un widget las adopta en su shadow root. Consulta Quién aplica una hoja de estilos.

Node.js

BEE Node carga módulos de Beyond en Node.js mediante hooks de módulos. Su adaptador resolution recibe una base, lee <base>resolution.json?target=node&format=esm una vez al iniciar el proceso y resuelve con él cada especificador simple de un módulo servido, ámbitos incluidos:

Shell
BEE_URL=https://<application host>/_r/12/ BEE_ADAPTER=resolution BEE_CACHE=.beyond/cache \
  node --import @beyond-js/bee-node/register app.mjs
  • Un módulo se obtiene solo de debajo de la base. Un especificador que el documento no resuelve es un error que nombra el especificador y el importador; un módulo integrado de Node va a Node.
  • Tu propio script conserva la resolución de Node para tus paquetes instalados; el documento responde primero.
  • Las respuestas se conservan durante el proceso. Con BEE_CACHE, las respuestas immutable también se guardan en disco y se reutilizan sin solicitud, que es lo que responde la base de un release: un proceso que vuelve a iniciar con la caché caliente no hace ninguna solicitud. Un servidor de desarrollo responde no-store, así que se le pregunta en cada inicio.
  • Un saludo inicial que falla detiene el proceso, nombrando el adaptador. Nada recurre a otro adaptador.

Deno

Deno lee directamente el import map de la base:

Shell
deno run --allow-import=<application host> \
  --import-map='https://<application host>/_r/12/importmap.json?target=node&format=esm' app.mjs

Sus direcciones son relativas a la URL del mapa, así que Deno solicita cada módulo a la base. Las salidas de target Node se ejecutan, módulos integrados node: incluidos; un módulo neutral respecto de la plataforma de un target de navegador se ejecuta mediante el mapa de navegador (?target=browser&format=esm). Deno necesita --allow-import para el host de entrega.

Durante el desarrollo

Un servidor de desarrollo responde los mismos /resolution.json y /importmap.json, calculados a partir del workspace, y también format=system. Por eso las mismas estrategias funcionan contra él, con las opciones de desarrollo.

El runtime de desarrollo (@beyond-js/local-2026, un nombre provisional) aplica las actualizaciones con un solo mecanismo en los cuatro entornos: reemplaza los módulos internos cuyo hash cambió y conserva el estado de los demás. Cada entorno solo aporta cómo importa una actualización (import() nativo, o el import propio de SystemJS en una página SystemJS) y si tiene un documento para las hojas de estilos.

  • De dónde vienen las notificaciones. Por defecto, del flujo de eventos del servicio, <origin>/events. Cualquier emisor que hable el mismo protocolo de eventos puede reemplazarlo, en otra URL o como un objeto en el mismo proceso; Workspace es uno de esos emisores. local.hmr.notify(event) entrega una notificación a mano. Las actualizaciones en sí siempre se solicitan al origen.
  • Los fallos conservan el último estado válido. Una fuente que no compila no cambia nada y su corrección se aplica; un código que lanza al evaluarse hace fallar esa actualización y la siguiente lo vuelve a evaluar; una hoja de estilos inválida o que no carga conserva la última válida.
  • Un consumidor que perdió eventos queda desactualizado. Después de que el servicio se reinicia, el runtime informa stale y no aplica nada más: reinicia el consumidor, o recarga la página.

Esto se ejecutó en Chrome con módulos ES nativos y con SystemJS, en Node.js mediante BEE Node y en Deno, con el flujo propio del servicio, un emisor externo y notify().

Mediciones

Medido el 2026-09-23 en una máquina de desarrollo con mucha carga compartida, en una red de loopback, con releases preparados por el pipeline real; medianas de cinco ejecuciones. En Chrome se emuló un viaje de ida y vuelta de 40 ms en cada solicitud. Compara las variantes entre sí; no son cifras de un servicio alojado.

Caso, Chrome, inicio en frío Listo, sin precarga Listo, con precarga Transferido
React, ESM nativo 244 ms 147 ms 233.9 kB
React, SystemJS 247 ms 148 ms 453.2 kB
Cuatro familias de widgets, ESM nativo 429 ms 335 ms 577.4 kB
Cuatro familias de widgets, SystemJS 432 ms 345 ms 981.3 kB
Caso, un renderizador de servidor de React En frío En caliente
Node.js 22, adaptador resolution de BEE Node 89 ms, 5 solicitudes 41 ms, ninguna solicitud
Deno 2.9.7, --import-map 55 ms, 5 solicitudes 19 ms, ninguna solicitud

Los valores predeterminados se desprenden de ellas:

  • La precarga está activada. Anunciar los módulos inmediatos hizo que una página en frío iniciara entre un 23 y un 40 % antes cuando existe un viaje de ida y vuelta; en loopback no costó nada medible.
  • Los módulos ES nativos siguen siendo el predeterminado. SystemJS fue igual de rápido aquí, pero transfirió entre 1.7 y 1.9 veces los bytes, porque su conversión reimprime la salida minificada.
  • Los import maps van en línea en el shell: de 1.1 a 6.1 kB en estos casos, una solicitud menos que un mapa cargado con src.
  • Los procesos de Node.js que inician a menudo usan BEE_CACHE: una caché caliente inicia sin ninguna solicitud y en la mitad del tiempo.

Otro entorno

Un entorno nuevo es un consumidor nuevo de los mismos dos documentos, no una entrega nueva. Necesita leer resolution.json o importmap.json de un origen, obtener módulos solo de ese origen y ejecutar módulos ES o módulos System.register. Para las actualizaciones de desarrollo, le da al runtime su función de import y, si lo tiene, un documento.