WU / DOCSUNIVERSAL MICROFRONTENDS
ES

Navegación y composición

Conecta la URL y las intenciones de navegación del shell con el montaje, desmontaje y estado de tus aplicaciones.

El shell es dueño de la navegación

El shell decide qué aplicación corresponde a cada ruta y utiliza montaje, desmontaje, eventos y estado para componerla. Astro puede resolver páginas; un router React/Vue puede gestionar rutas internas de una aplicación. El core WU no incluye wu.router ni wu.navigate(): conecta el mecanismo de navegación que utilice tu shell con su lifecycle.

metadata.routes en wu.json es información descriptiva. El parser valida strings, duplicados y límites, pero no instala handlers de History API. wu.routes no vacío se rechaza en Framework 4 y no debe usarse como receta de routing.

Dos niveles de rutas

Nivel Ejemplo Responsable
Página del portal /docs/framework/state Router de archivos Astro
Sección dinámica del shell /workspace/catalog Controlador/router del shell
Vista interna de una app /products/:id dentro de catalog Router de esa app

La URL base de descarga, como /apps/catalog, es un recurso técnico y no tiene por qué coincidir con la ruta de navegación. Define por separado el base del bundle, el base del router interno y la ruta que el usuario ve.

Conectar una intención de navegación

Este ejemplo implementa una convención del shell; shell:navigate no activa un router integrado:

const routeTable = new Map([
  ['/workspace/catalog', 'catalog'],
  ['/workspace/reports', 'reports'],
]);

let activeApp = null;
let transition = Promise.resolve();

function showRoute(path) {
  transition = transition.catch(() => {}).then(async () => {
    const nextApp = routeTable.get(path);
    if (!nextApp || nextApp === activeApp) return;
    if (activeApp) await wu.unmount(activeApp, { force: true });
    activeApp = null;
    await wu.mount(nextApp, '#workspace-slot');
    activeApp = nextApp;
  });
  return transition;
}

const stop = wu.on('shell:navigate', ({ data }) => {
  if (!routeTable.has(data?.path)) return;
  history.pushState(null, '', data.path);
  showRoute(data.path).catch(console.error);
});

const onPopState = () => showRoute(location.pathname).catch(console.error);
window.addEventListener('popstate', onPopState);
await showRoute(location.pathname);

// Al retirar el controlador del shell:
// stop();
// window.removeEventListener('popstate', onPopState);

La tabla limita qué rutas y apps acepta. La cola conserva orden cuando el usuario navega varias veces antes de terminar una carga. El core también coordina ownership del contenedor; mantener un estado claro en el shell evita que una promesa vieja actualice controles de navegación de una ruta nueva.

Elementos dentro de Shadow DOM

wu.mount(name, selector) resuelve el selector con document.querySelector. Ese selector no cruza ShadowRoots y la firma actual espera un string, no un HTMLElement. Para que el shell localice el slot, colócalo en su light DOM o utiliza una composición que exponga un nodo accesible por selector.

Dentro de un lifecycle, usa el container entregado para manipular la raíz local; no vuelvas a buscarla globalmente por ID. El adapter Vue del repositorio ilustra por qué una raíz estable debe ser un hermano del indicador de loading y no su contenedor gestionado por el shell.

Keep-alive y cambio de ruta

hide preserva estado y listeners; funciona cuando mantienes el contenedor de la app. Cambiar muchas apps sobre un único slot requiere una decisión explícita: desmontar el dueño anterior o conservar contenedores separados para cada app que permanezca viva. No uses keep-alive como sinónimo de cachear módulos; son recursos distintos.

Si Astro reemplaza páginas mediante navegación cliente, el bootstrap debe acompañar ese lifecycle: libera listeners y mounts de la página anterior y conecta los nuevos slots. Una importación de script deduplicada no significa que todos los nodos futuros queden montados automáticamente.

Roles de UI

wu.setPrincipal({ id: 'u1', roles: ['catalog-reader'] }) alimenta wu.can('catalog'). El montaje consulta los roles requeridos por el manifest y puede rechazar con WU_ACCESS_DENIED. Esto ayuda a mantener navegación y vistas coherentes; las APIs de datos deben autorizar cada petición en el servidor.

Referencia de implementación

Validación de rutas descriptivas: src/core/wu-manifest.js; acceso: src/core/wu-core.js y src/core/wu-core.js; selector: src/core/wu-core.js; transición de contenedor: src/core/wu-core.js; convención usada por MCP: src/core/wu-mcp-bridge.js. Pruebas: tests/unit/shared-container-navigation.test.js, tests/unit/sandbox-container-ownership.test.js, tests/unit/rbac.test.js.

WU SE CONSTRUYE CONTIGO

¿Encontraste un bug? ¿Tienes una idea?

Tu experiencia mejora WU. Cuéntanos qué falla o ayuda a sostener su desarrollo.