Salidas, estilos y recursos
Las cuatro familias de recursos de una versión de paquete (módulos, estilos, mapas y recursos estáticos), cómo un import selecciona el JavaScript o la hoja de estilos de un módulo público, la hoja de estilos compartida de un paquete y cómo se anuncian los recursos complementarios.
- Disponibilidad: Experimental
- Evidencia: Leído del código fuente
- Referencia
Cuatro familias bajo una misma identidad
Cada versión de un paquete tiene cuatro familias hermanas. Comparten el prefijo de identidad, de modo que un registro, un paquete, una versión o una subruta nunca es válido en una familia e inválido en otra.
| Familia | Ruta | Tipo de medio | Opciones |
|---|---|---|---|
| Módulo | /m/[<registry>/]<package>@<version>/modules/<subpath> |
application/javascript |
Sí |
| Estilo | /m/[<registry>/]<package>@<version>/styles/<subpath> |
text/css |
Sí |
| Mapa | /m/[<registry>/]<package>@<version>/maps/<subpath> |
application/json (source map, revisión 3) |
Sí |
| Recurso estático | /m/[<registry>/]<package>@<version>/assets/<path> |
El tipo de medio del archivo | No |
El segmento de familia es el que sigue a <package>@<version>. Un registro o una subruta de módulo que casualmente se llame styles o assets se lee como antes.
Módulos
Una respuesta correcta de módulo contiene JavaScript, un ETag fuerte y el Cache-Control del servicio. Consulta Caché y releases para ambos encabezados.
Una solicitud devuelve un módulo público. El CDN nunca fusiona módulos públicos en un solo archivo ni divide uno en varios: el módulo público es la unidad de entrega, y sus imports de otros módulos públicos siguen siendo referencias simples que la resolución asigna a URL.
Estilos
/m/@example/app@1.0.0/styles/core/router?target=browser&format=esmUn estilo se direcciona con la subruta de un módulo público, ~root incluido. Es la hoja de estilos de ese módulo o bien un módulo de estilo, que es un módulo público cuya salida es CSS. Acepta las mismas opciones que la solicitud del módulo, con la misma validación.
Los estilos forman parte del cierre alcanzable de una aplicación. La preparación los rastrea como elementos de sus módulos. Una hoja de estilos nunca se descarta ni se inyecta en el JavaScript: es una salida separada, que enlaza o adopta quien entrega el módulo.
Un url() en una hoja de estilos, o un import de un archivo estático desde el código fuente, se escribe como ../assets/<path in the package>, relativo a donde este contrato sirve el módulo o su hoja de estilos. Por eso una misma salida funciona en cualquier origen.
Seleccionar una salida
Un módulo público puede tener varias salidas. El código fuente elige una con su especificador de import:
| Especificador | Selecciona |
|---|---|
pkg/sub |
El JavaScript del módulo público ./sub. Es el predeterminado de todo import. |
pkg/sub.css |
La hoja de estilos de ./sub: el módulo de estilo, o la hoja de estilos que produce el módulo. Cuando el paquete publica una subruta literal ./sub.css, como hacen los paquetes npm que exportan archivos CSS, se selecciona esa subruta. |
pkg/sub.js, pkg/sub.mjs |
El JavaScript de ./sub.js cuando el paquete lo publica, y si no el de ./sub |
| Cualquier otra extensión | Nada especial: forma parte de la subruta |
La regla se comprueba cuando se compila o analiza el módulo que importa, y una selección incorrecta falla ahí, nunca en la entrega:
| Diagnóstico | Cuándo |
|---|---|
OUTPUT_NOT_FOUND |
Un módulo que solo es una hoja de estilos importado sin .css (el mensaje nombra el especificador que hay que escribir), o .css de un módulo que no produce hoja de estilos |
OUTPUT_AMBIGUOUS |
El especificador nombra dos módulos públicos distintos, como una subruta literal ./sub.css y un módulo ./sub con su propia hoja de estilos. No se adivina nada. |
STYLE_BINDING_UNSUPPORTED |
Se pidió un valor a una hoja de estilos: import sheet from 'pkg/sub.css', un import con nombre de ella, o with { type: 'css' } |
Una hoja de estilos seleccionada es una relación de estilo, no un import de código. Se quita del JavaScript compilado, import 'pkg/sub.css' no carga el código de ./sub, y el inventario de la preparación la lista como el elemento style de su módulo. Un documento de resolución asigna un especificador a una dirección /styles/ solo cuando el especificador termina en .css.
Quién aplica una hoja de estilos
Nada aplica CSS por una extensión: ni un navegador, ni SystemJS, ni un host de Node o de Deno lo hacen. Quien entrega el módulo aplica sus hojas de estilos de forma explícita:
- Un documento enlaza las hojas de estilos de los módulos que carga fuera de cualquier widget. El shell de una aplicación publicada enlaza las inmediatas en su cabecera y las diferidas cuando el punto de entrada ya cargó.
- Un widget adopta, dentro de su propia shadow root, su hoja de estilos y las de los módulos públicos que importa, mediante el registro de estilos del runtime. Un widget anidado tiene su propia raíz. Consulta Widgets y frameworks de vista.
- Node.js y Deno no cargan ninguna hoja de estilos.
La hoja de estilos compartida de un paquete
Un paquete puede publicar una hoja de estilos que comparten todos sus widgets: el módulo de estilo ./global. Publicarlo es toda la declaración; no hay otra marca.
- Cada módulo widget de ese paquete depende de ella de forma implícita: preparar un solo widget prepara también la hoja.
- Cada widget la adopta dentro de su propia raíz, antes de sus propias hojas, y un widget de otro paquete no lo hace.
- Un paquete sin
./globalno produce ninguna solicitud de ella. - En un servidor de desarrollo, una actualización de la hoja la reemplaza en cada widget de ese paquete y en ningún otro; una hoja rota conserva la última válida.
Esto es distinto de seleccionar una hoja de estilos con .css: los widgets de su propio paquete adoptan la hoja compartida, mientras que .css selecciona la hoja de estilos de cualquier módulo público que nombres.
Source maps
/m/@example/app@1.0.0/maps/core/router?target=browser&format=esmUn mapa es el source map externo del JavaScript que seleccionan las mismas opciones. Solicítalo con las opciones del módulo al que pertenece.
Un mapa generado nunca nombra una ruta de la máquina que lo compiló. Cada entrada de sources se escribe bajo una raíz virtual, beyond://<package>@<version>/<path in the package>, para el código y las hojas de estilos en ambos formatos; lo que se generó para la unidad se nombra bajo ~generated/. Las salidas son reproducibles: el repositorio de Packages registra que las mismas fuentes, extraídas en dos directorios distintos, producen salidas, mapas y digests idénticos byte por byte. Los mapas de desarrollo son la excepción y conservan nombres relativos al directorio del módulo.
Que existan mapas para un release depende de un ajuste de la aplicación, sourcemaps:
| Valor | Efecto |
|---|---|
restricted (predeterminado) |
Los mapas se conservan y se sirven solo a un miembro: 401 sin acceso y 403 para un invitado. El encabezado SourceMap se envía solo a quien se le serviría el mapa. |
public |
Los mapas se exponen junto con el release |
none |
No se conservan mapas; el release se prepara con sourcemap=none |
Promover un release que expone mapas públicos exige una confirmación explícita. Consulta Releases, promoción y reversión.
Recursos estáticos
/m/@example/app@1.0.0/assets/images/logo.pngUn recurso estático pertenece al paquete, no a uno de sus módulos. Su ruta es el archivo dentro del paquete, con sus barras y su extensión.
- Un paquete declara recursos en un manifiesto de módulo (
assets, relativo al directorio del módulo) o en supackage.json(beyond.assets). Un archivo al que hace referencia unurl()o un import del código fuente también se incluye en el inventario de un release. Un archivo que simplemente existe en el paquete no es un recurso, y un recurso que el servicio no tiene es404 OUTPUT_NOT_AVAILABLE. - Una solicitud de recurso no acepta opciones. Cualquier consulta es
400 OPTION_INVALID. - Los segmentos vacíos, los segmentos
.y.., las barras codificadas, las barras invertidas y los caracteres de control son400 IDENTITY_INVALID, de modo que un recurso tiene una sola ruta y una solicitud nunca sale del paquete.
Cómo se anuncian los recursos complementarios
Un servicio anuncia un recurso complementario solo cuando la solicitud lo pide y el servicio lo sirve:
- Con
css=true, la respuesta de un módulo agrega un encabezadoLinkhacia su hoja de estilos. - Con
types=true, la respuesta de un módulo agrega un encabezadoLinkhacia sus declaraciones, en un servicio que las produce. - La respuesta de una hoja de estilos puede llevar un encabezado
SourceMapque apunta a su mapa externo.
Un servicio que no puede servir el recurso complementario rechaza la opción con OPTION_UNSUPPORTED en lugar de anunciar un recurso que no tiene. Nunca construyas la URL de un recurso complementario adivinándola: usa el encabezado o el inventario del release.
En código
import { ResourcePath } from '@beyond-js/artifact-api';
const style = ResourcePath.parse('/m/@example/app@1.0.0/styles/core/router');
style.kind; // 'style'
style.media; // 'text/css'
style.options(query); // the same Options as the module request
const asset = ResourcePath.parse('/m/@example/app@1.0.0/assets/images/logo.png');
asset.path; // 'images/logo.png'
asset.options(query); // undefined; any query throws OPTION_INVALID
ResourcePath.format({ kind: 'map', identity: style.identity }); // '/m/@example/app@1.0.0/maps/core/router'