SystemJS

El modo de carga system de una aplicación: salidas System.register cargadas por SystemJS 6.15.1, que cada release guarda como su propio loader.js, y cómo cargar las mismas salidas desde una página propia.

  • Disponibilidad: Experimental
  • Evidencia: Ejecución registrada
  • Guía práctica

Estado inicial

Una aplicación elige un modo de carga en sus ajustes:

loader Significado
esm (predeterminado) Módulos ES nativos con un import map. Consulta ESM nativo e import maps.
system Salidas System.register cargadas por SystemJS, que el release guarda como su propio loader.js

El modo se lee cuando se prepara un release. Cambiarlo afecta a los releases que se preparen después; un release existente conserva el modo con el que se preparó. Elige system para navegadores sin import maps; ESM nativo sigue siendo el predeterminado porque transfiere menos bytes (consulta las mediciones).

El cargador que trae un release

Un release preparado con loader: system guarda, bajo su prefijo de release:

Documento Contenido
index.html El shell: las hojas de estilos inmediatas, el import map en línea como <script type="systemjs-importmap"> con direcciones ligadas al release, <link rel="preload" as="script"> para los módulos inmediatos, y luego loader.js y bootstrap.js
loader.js SystemJS 6.15.1: su compilación s.min.js, su extra named-register y un extra de espacios de nombres de una línea del CDN
bootstrap.js Un script clásico que llama a System.import(entry) y enlaza las hojas de estilos diferidas cuando la entrada ya cargó

El cargador forma parte del release, como cualquier otro documento: ninguna página llega a un origen de terceros en tiempo de ejecución, y un release conserva el cargador con el que se validó aunque el servicio se actualice.

Por qué esta compilación:

  • s.js contiene lo que necesitan las salidas System.register de Packages: registro anónimo, setters y enlaces vivos, export *, ciclos, context.import() para un import() dinámico, context.meta.url, e import maps con ámbitos, en línea o cargados con src.
  • No se usa la compilación completa system.js: su carga de scripts globales convertiría un script que no registra nada en un módulo vacío en lugar de un error, y su tipo de módulo CSS aplicaría una hoja de estilos por una extensión. En cambio, un release enlaza sus hojas de estilos de forma explícita.
  • named-register acepta paquetes que nombran sus registros, System.register('name', …).
  • El extra de espacios de nombres le da a un importador el espacio de nombres de un módulo sin exports cuando enlaza, como hace ESM nativo. Sin él, import * as x de un módulo de efectos secundarios queda undefined en SystemJS.

Los propios errores de SystemJS llegan a la página sin cambios, por ejemplo su error #8 para un especificador fuera del import map, #2 para un script que no registra nada y #7 para un módulo que no responde.

La solicitud

La identidad, la ruta y todas las demás opciones son las mismas que en el modo ESM. Solo cambia format:

Text
/m/@example/[email protected]/modules/core/router?target=browser&format=system

Un servicio publicado la sirve como cualquier otra salida preparada: una solicitud válida de un módulo cuya salida system no se preparó es 404 OUTPUT_NOT_AVAILABLE. Un servidor de desarrollo convierte su módulo ES a System.register al solicitarlo, actualizaciones incluidas, así que la misma página funciona contra ambos orígenes.

Cargar desde una página propia

Fuera del shell generado, carga SystemJS desde el release y luego dale el import map del release con src. Las direcciones del mapa son relativas a su URL, así que SystemJS las resuelve en la base del release sin que tu página conozca ninguna dirección de módulo:

HTMLsystem.html
<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<title>SystemJS from a release</title>
		<!--
			https://app.example/_r/12 is the base of one release prepared in the `system` loader mode: the
			application host followed by /_r/<release number>. Replace it with yours; it is the only value
			that changes between releases and origins.

			1. The import map of the release, loaded by SystemJS itself. Its addresses are relative to the
			   map's URL, so every module is requested from the release base.
			2. SystemJS 6.15.1 as the release stores it. Do not load another copy.
		-->
		<script type="systemjs-importmap" src="https://app.example/_r/12/importmap.json?target=browser&format=system"></script>
		<script src="https://app.example/_r/12/loader.js"></script>
	</head>
	<body>
		<pre id="output">Loading…</pre>
		<script>
			// System.import waits for the import map, then loads the module and what it imports.
			System.import('@example/shared/text').then(
				module => (document.getElementById('output').textContent = Object.keys(module).join('\n')),
				error => (document.getElementById('output').textContent = String(error))
			);
		</script>
	</body>
</html>

loader.js es un script clásico, así que se carga desde otro origen sin encabezados especiales; los módulos y el mapa se pueden leer desde otros orígenes. No agregues otra copia de SystemJS: una página tiene un único registro System, y el cargador del release es aquel con el que se validaron sus salidas.

Un cargador propio

Un cargador propio necesita las mismas dos cosas: el documento de resolución del release, para convertir un especificador público en una URL relativa al origen, y un origen base que anteponer. Resolution.resolve(specifier, importer) aplica los ámbitos por ti. Conserva los especificadores públicos y los límites de los módulos: un cargador que reescribe un import público como la ruta a un archivo interno rompe el contrato con el que se compilaron los módulos.

Límites

Si falla

Respuesta Significado
400 OPTION_UNSUPPORTED Este servicio no produce format=system en absoluto
404 OUTPUT_NOT_AVAILABLE El servicio puede tenerla, y este release no se preparó con ella
Error #8 de SystemJS El especificador no está en el import map: un mapa de otro release, o un módulo que la resolución no lista