Skip to content

vitral

Feito de partes. Visto como um todo.

Junte micro-frontends de qualquer framework numa página só, sem configuração de build no host.

3,4 kBcódigo de host mínimo, com brotli
-57%de tempo na primeira visita contra o Module Federation com React compartilhado
4,6xmais rápido para trocar de área que o Next.js Multi-Zones
10frameworks, como host e como remote

Medido no Chromium com rede Slow 4G, mediana de 7 visitas. Método.

Como funciona ​

Três equipes (React, Vue, Angular) publicam um vitral.json cada uma num CDN. O host lê as URLs com configure e monta os três remotes na mesma página.

Cada equipe publica o próprio pedaço da página com vite build. O host recebe a URL de cada pedaço e monta tudo no navegador. Por que o vitral explica quando usar e quando não usar.

O host só precisa da URL ​

Registre a URL do vitral.json de cada remote e renderize. Nenhum plugin no build do host.

jsx
import { configure } from 'vitral'
import { Remote } from 'vitral/react'

configure({
  remotes: { carrinho: 'https://cdn.empresa.com/carrinho/vitral.json' },
})

export const App = () => <Remote name="carrinho" props={{ userId: 42 }} />

O remote é um componente comum ​

Exporte o componente como default e adicione o plugin. O build gera o vitral.json.

js
// vite.config.js
import vue from '@vitejs/plugin-vue'
import vitral from 'vitral/vite'

export default { plugins: [vue(), vitral()] }

Qualquer framework ​

React, Next, Vue, Nuxt, Angular, Svelte, Solid, Preact, Lit e JS puro. Host e remote não precisam combinar.

vue
<template>
  <VitralRemote name="carrinho" :props="{ userId }">
    <template #fallback>Carregando…</template>
  </VitralRemote>
</template>
html
<vitral-remote name="carrinho" props='{"userId": 42}'></vitral-remote>

CSS isolado ​

O CSS de cada remote vale só dentro dele. Tailwind funciona. Para isolar também o CSS do host, use Shadow DOM.

css
/* CSS do remote */
.botao { color: red }

/* depois do build */
[data-vitral-scope="carrinho"] .botao { color: red }
jsx
<Remote name="carrinho" isolate="shadow" />

Um remote que falha não derruba a página ​

Cada remote mostra o próprio erro. tentarDeNovo monta só aquele remote de novo.

jsx
<Remote
  name="carrinho"
  fallback={<p>Carregando…</p>}
  error={(erro, tentarDeNovo) => <button onClick={tentarDeNovo}>Tentar de novo</button>}
  onError={(erro) => log(erro.code)}
/>

Pequeno ​

O código de host mínimo tem 3,4 kB com brotli. Sem build no host, uma tag de script basta.

html
<script type="module" src="https://cdn.jsdelivr.net/npm/vitral/dist/auto.js"></script>

<vitral-remote src="https://cdn.empresa.com/carrinho/vitral.json"></vitral-remote>

Comparação ​

Module Federationsingle-spaqiankunNext.js Multi-Zonesvitral
Configuração no hostPlugin no buildRoot config e import mapregisterMicroApps e startUm app Next por zona e rewritesconfigure({ remotes })
FrameworksCombinar dependências em sharedUm adaptador por frameworkQualquer, com entrada HTMLSó NextQualquer
Isolamento de CSSNenhumNenhumShadow DOM ou prefixoPor páginaEscopo automático ou Shadow DOM
Código de host (brotli)19,4 kB5,8 kB37,9 kBRuntime do Next em cada zona3,4 kB
Trocar de áreaSem recarregarSem recarregarSem recarregarRecarrega a páginaSem recarregar
Confere o hash do JS (SRI)Não, por padrãoNão, por padrãoNão, por padrãoNão, por padrãoSim, quando o manifesto tem hash

Comparação com a configuração padrão de cada ferramenta. Plugins e configuração extra podem mudar estes valores.

Vindo de uma dessas ferramentas? Veja Migração.