Navegação e composição
Conecte a URL e as intenções de navegação do shell à montagem, desmontagem e estado das suas aplicações.
O shell é responsável pela navegação
O shell decide qual aplicação corresponde a cada rota e usa montagem, desmontagem, eventos e estado para compô-la. Astro pode resolver páginas; um roteador React/Vue pode gerenciar rotas internas de uma aplicação. O core WU não inclui wu.router nem wu.navigate(): conecte o mecanismo de navegação usado pelo seu shell ao ciclo de vida.
metadata.routes em wu.json é informação descritiva. O parser valida strings, duplicados e limites, mas não instala handlers da History API. wu.routes não vazio é rejeitado no Framework 4 e não deve ser usado como receita de roteamento.
Dois níveis de rotas
| Nível | Exemplo | Responsável |
|---|---|---|
| Página do portal | /docs/framework/state |
Roteador de arquivos Astro |
| Seção dinâmica do shell | /workspace/catalog |
Controlador/roteador do shell |
| Vista interna de uma app | /products/:id dentro de catalog |
Roteador dessa app |
A URL base de download, como /apps/catalog, é um recurso técnico e não precisa corresponder à rota de navegação. Defina separadamente a base do bundle, a base do roteador interno e a rota vista pelo usuário.
Conectar uma intenção de navegação
Este exemplo implementa uma convenção do shell; shell:navigate não ativa um roteador 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);
A tabela limita quais rotas e apps são aceitas. A fila mantém a ordem quando o usuário navega várias vezes antes de um carregamento terminar. O core também coordena a propriedade do contêiner; manter um estado claro no shell evita que uma promise antiga atualize controles de navegação de uma nova rota.
Elementos dentro de Shadow DOM
wu.mount(name, selector) resolve o seletor com document.querySelector. Esse seletor não atravessa ShadowRoots e a assinatura atual espera uma string, não um HTMLElement. Para que o shell localize o slot, coloque-o no light DOM ou use uma composição que exponha um nó acessível por seletor.
Dentro de um ciclo de vida, use o container entregue para manipular a raiz local; não a procure globalmente por ID outra vez. O adaptador Vue do repositório ilustra por que uma raiz estável deve ser irmã do indicador de carregamento, e não seu contêiner gerenciado pelo shell.
Keep-alive e mudança de rota
hide preserva estado e listeners; funciona quando você mantém o contêiner da app. Trocar muitas apps em um único slot exige uma decisão explícita: desmontar o proprietário anterior ou manter contêineres separados para cada app que continuar viva. Não use keep-alive como sinônimo de manter módulos em cache; são recursos diferentes.
Se Astro substituir páginas por navegação cliente, o bootstrap deve acompanhar esse ciclo de vida: libere listeners e mounts da página anterior e conecte os novos slots. Uma importação de script deduplicada não significa que todos os nós futuros serão montados automaticamente.
Papéis de UI
wu.setPrincipal({ id: 'u1', roles: ['catalog-reader'] }) alimenta wu.can('catalog'). A montagem consulta os papéis exigidos pelo manifesto e pode rejeitar com WU_ACCESS_DENIED. Isso ajuda a manter a navegação e as vistas coerentes; as APIs de dados devem autorizar cada solicitação no servidor.
Referência de implementação
Validação de rotas descritivas: src/core/wu-manifest.js; acesso: src/core/wu-core.js e src/core/wu-core.js; seletor: src/core/wu-core.js; transição de contêiner: src/core/wu-core.js; convenção usada pelo MCP: src/core/wu-mcp-bridge.js. Testes: tests/unit/shared-container-navigation.test.js, tests/unit/sandbox-container-ownership.test.js, tests/unit/rbac.test.js.