WU / DOCSUNIVERSAL MICROFRONTENDS
ES

Lifecycle y ownership

Registro, mount, props vivas, desmontaje, keep-alive y limpieza de recursos por aplicación.

Consulta las versiones, cambios y requisitos en Framework 4.0 y CLI 1.2.

Registro no equivale a montaje

wu.init registra metadatos y permisos. wu.define registra funciones. wu.mount resuelve una app, prepara su contenedor, carga su entry si falta la definición y ejecuta el renderer. El nombre une esos tres pasos.

import { wu } from 'wu-framework';

let stop = () => {};
let abort = null;

wu.define('activity', {
  mount(container, { wu: appWu }) {
    abort = new AbortController();
    const output = document.createElement('output');
    const refresh = () => {
      output.textContent = String(appWu.store.get('activity.count') ?? 0);
    };
    container.replaceChildren(output);
    stop = appWu.store.on('activity.count', refresh);
    refresh();
    container.addEventListener('click', () => {
      appWu.emit('activity:opened', { source: 'counter' });
    }, { signal: abort.signal });
  },
  update(container, props) {
    container.setAttribute('aria-label', props.label ?? 'Actividad');
  },
  unmount(container) {
    stop();
    abort?.abort();
    container.replaceChildren();
  },
});

La app necesita solicitudes y grants para leer activity.count y emitir activity:opened. El ejemplo conserva la facade recibida; el import de wu se utiliza para registrar el lifecycle.

Slots disponibles

Slot Firma / uso
mount (container, { appName, wu }); obligatorio
unmount (container, context); libera renderer, listeners y recursos propios
update (container, nextProps); actualización sin desmontar
hydrate (container, { appName, wu, props }); adopta marcado SSR
deactivate (container); se invoca antes de ocultar con keep-alive
activate (container); reactiva una app preservada

Los slots admiten promesas. Rechazar una promesa en mount permite que el core limpie el intento y consulte la recuperación. Ocultar un error sin renderizar nada hace que WU pueda considerar exitoso el montaje; lanza errores cuando realmente no puedas montar.

Secuencia observable

El montaje ejecuta beforeLoad, el hook de plugin beforeMount, crea el sandbox, ejecuta afterLoad, obtiene o carga la definición, ejecuta beforeMount, espera estilos y llama hydrate o mount. Luego registra el estado montado y ejecuta hooks posteriores.

afterLoad se ejecuta después de crear el sandbox y antes de resolver/cargar el lifecycle. Usa afterMount cuando necesites reaccionar al árbol ya montado.

El core serializa las transiciones sobre un mismo contenedor. Una app no debe borrar un nodo cuya propiedad ya se transfirió a otra. También existe conteo de referencias y desmontaje diferido para absorber ciclos de integración como React StrictMode. Si varios consumidores comparten una app, cada montaje debe tener un desmontaje correspondiente.

Props vivas

const updated = await wu.update('activity', { label: 'Actividad reciente' });
if (!updated) console.info('La app no aplicó esta actualización');

update no fabrica un renderer si la app no implementa ese slot. Los adapters React y Vue conservan props y actualizan su raíz sin remount. Las props iniciales se configuran en el registro del adapter o en SSR; WuLifecycle.mount no declara context.props para el montaje normal.

Ocultar y destruir

await wu.hide('activity');
console.log(wu.isHidden('activity'));
await wu.show('activity');
await wu.unmount('activity', { force: true });

hide conserva DOM, iframe cuando existe, estado, timers y listeners. La aplicación sigue consumiendo recursos; deactivate es el lugar para pausar trabajo propio que no interesa mientras está oculta. show restaura visibilidad y ejecuta activate sin volver a cargar el entry.

unmount resuelve keepAlive en este orden: force obliga a destruir; de lo contrario prevalece la opción de la llamada, luego la config de la app y finalmente false. Desmontar por completo revoca la identidad scoped, listeners y handlers asociados. Una referencia a context.wu conservada después del desmontaje falla con WU_APP_SCOPE_REVOKED.

wu.destroy() limpia el runtime completo. Úsalo cuando el shell deja de existir, no para cambiar una sola sección. wu.app(name, config) entrega un wrapper con mount, unmount, hide, show, remount, reload, verify, start, stop y destroy.

Wrapper: registro diferido y concurrencia

wu.app(name, config) agrupa la identidad, configuración y destino de una aplicación. Crear el wrapper conserva esos datos; el registro efectivo ocurre al montar, a través del core y de su validación de manifest y permisos. Si el core aún no se ha iniciado, el wrapper inicia esa configuración antes de montar.

const widget = wu.app('widget', {
  url: '/apps/widget',
  container: '#widget-slot',
  framework: 'vue',
  grants: [],
});
await widget.mount();
console.log(widget.isMounted, widget.info.container);
await widget.hide();
await widget.show();
await widget.unmount({ force: true });

La URL debe servir el manifest de widget. mount(selector) permite elegir otro destino y lo conserva para llamadas posteriores sin argumento. Los métodos de montaje, desmontaje, visibilidad, remount y reload resuelven al mismo wrapper, para poder inspeccionar su estado al terminar.

Miembro Uso
mount(selector?) / start(selector?) Registrar si hace falta y montar sobre un selector string
unmount(options?) / stop() Desmontar; stop utiliza las opciones por defecto
hide() / show() Conservar y reactivar una app montada
remount(selector?) Forzar desmontaje y volver a montar
reload() Desmontar, limpiar cachés del loader/manifest disponibles y montar de nuevo
isMounted / isHidden Consultar estado del wrapper y del core
info Nombre, URL, selector, montaje y status
verify() Inspeccionar registro, selector y Shadow DOM del contenedor

Si otro init está en vuelo, el wrapper lo espera y registra su app después si aún falta. Dos mounts concurrentes sobre el mismo wrapper comparten una promesa de registro; cada montaje sigue participando en el ownership/conteo de referencias del core. Un fallo libera esa promesa para permitir un reintento. Un registro existente del host se conserva, sin sobrescribir sus grants con los de otro wrapper.

reload() no invalida el caché nativo de módulos ESM del navegador ni garantiza descargar una versión diferente del mismo URL. Para actualizar una versión desplegada, publica entries con identidad de build y coordina su carga desde el shell.

verify().container.hasContent inspecciona los hijos del ShadowRoot del slot; un resultado false no demuestra que un renderer con ownership propio o light DOM esté vacío. WuApp.destroy() elimina la app del mapa público, pero no limpia todos los registros de manifest asociados. Para retirar un renderer usa unmount; para reinicializar el shell completo usa wu.destroy() y un nuevo init, en lugar de tratar el destroy del wrapper como una operación general de sustitución de identidad.

Referencia de implementación

Slots: src/index.d.ts; definición: src/core/wu-core.js; montaje: src/core/wu-core.js; actualización: src/core/wu-core.js; teardown: src/core/wu-core.js; keep-alive: src/core/wu-core.js; wrapper: src/core/wu-app.js. Pruebas: tests/unit/keep-alive.test.js, tests/unit/props-channel.test.js, tests/unit/shared-container-navigation.test.js, tests/unit/scoped-events-teardown.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.