Arquitetura de Interfaces: Microfrontends utilizando Web Components
No desenvolvimento de sistemas, é comum adotarmos abordagens que diminuam cada vez mais o acoplamento entre diferentes serviços e rotinas…
Arquitetura de Interfaces: Microfrontends utilizando Web Components
No desenvolvimento de sistemas, é comum adotarmos abordagens que diminuam cada vez mais o acoplamento entre diferentes serviços e rotinas, visando melhorar a produtividade das equipes de um projeto.
É comum abordarmos microsserviços em discussões sobre arquitetura de soluções. Mas, da mesma forma que estruturamos nosso backend em partes bem definidas, o mesmo pode ser feito para as nossas interfaces. Nos parágrafos a seguir, será demonstrado como podemos criar uma arquitetura de microfrontend utilizando web components.
O Caso de Uso
Antes de partirmos para a demonstração prática, gostaria de elucidar o caso de uso para o nosso exemplo de web component.
Imagine que você possua uma aplicação de cadastro de peças de email. Você estrutura a sua interface com formulário de login, listagem e cadastro de peças.
Nesse sentido, a empresa dispõe de outros sistemas de CRM e OMNI channel que utilizam essas peças para realizar algumas comunicações com os clientes.
A gerência não deseja que os sistemas tenham que dispor de um formulário de cadastro de novas peças e, ao mesmo tempo, não desejam que o usuário tenha que navegar entre dois sistemas diferentes para realizar esse cadastro.
Com isso, trabalharemos em expor um web component de cadastro de novas peças para que ambos os sistemas não tenham que se preocupar com atualizações envolvendo novos inputs, economizando horas de desenvolvimento redundante.
Gerando o Web Component
O exemplo abaixo foi construído como prova de conceito da aplicação da nossa estratégia de web components para uso como microfrontend.
Como stack da aplicação principal, utilizou-se React+Vite. O projeto foi estruturado da seguinte forma:
├───public
└───src
├───assets
├───components
│ └───TemplatesCrud
|───embed
| └─── template-crud.tsx
└─── App.tsx
Nosso componente TemplateCrud é a casca principal que contém os elementos e a consulta aos dados da API, contendo duas propriedades de api-url e bearer-token para simplificar seu uso.
Em App.tsx. dispomos de uma simples tela de login e um uso de demonstração do nosso web component.
O arquivo template-crud.tsx define como vamos renderizar nosso componente TemplatesCrud em um arquivo js para ser utilizado em outras aplicações. Sua estrutura pode ser padrão na criação de outros web components:
import { createRoot, type Root } from 'react-dom/client';
import React from 'react';
import TemplatesCrud from '../components/TemplatesCrud';
class TemplatesCrudElement extends HTMLElement {
private root: Root | null = null;
static get observedAttributes() {
return ['api-url', 'bearer-token'];
}
connectedCallback() {
this.mountReact();
}
attributeChangedCallback(_name: string, oldValue: string, newValue: string) {
if (oldValue !== newValue) {
this.mountReact();
}
}
disconnectedCallback() {
this.unmountReact();
}
private unmountReact() {
if (this.root) {
this.root.unmount();
this.root = null;
}
}
private mountReact() {
const apiUrl = this.getAttribute('api-url');
const bearerToken = this.getAttribute('bearer-token');
// Validation rule: Block render if api-url or bearer-token is missing
if (!apiUrl || !bearerToken) {
this.unmountReact();
this.innerHTML = `
<div style="
font-family: 'Inter', system-ui, sans-serif;
color: #ef4444;
background: #fef2f2;
padding: 24px;
border: 1px solid #fee2e2;
border-radius: 12px;
max-width: 500px;
margin: 20px auto;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
">
<h3 style="margin-top: 0; margin-bottom: 8px; font-weight: 600; font-size: 16px; display: flex; align-items: center; gap: 8px;">
⚠️ Acesso Bloqueado (Microfrontend)
</h3>
<p style="margin: 0; font-size: 14px; color: #7f1d1d; line-height: 1.5;">
Os parâmetros obrigatórios de segurança não foram fornecidos pelo sistema Hospedeiro (Host).
</p>
<ul style="margin: 12px 0 0 0; padding-left: 20px; font-size: 13px; color: #991b1b;">
${!apiUrl ? '<li>Atributo <strong>api-url</strong> está ausente.</li>' : ''}
${!bearerToken ? '<li>Atributo <strong>bearer-token</strong> está ausente.</li>' : ''}
</ul>
</div>
`;
return;
}
// Mount React Root if it doesn't exist
if (!this.root) {
// Clear fallback HTML
this.innerHTML = '';
this.root = createRoot(this);
}
// Render the Core React Component
this.root.render(
<React.StrictMode>
<TemplatesCrud
apiUrl={apiUrl}
bearerToken={bearerToken}
/>
</React.StrictMode>
);
}
}
// Define the custom element if it hasn't been registered yet
if (!customElements.get('templates-crud-microfrontend')) {
customElements.define('templates-crud-microfrontend', TemplatesCrudElement);
}
É importante destacar alterações necessárias no arquivo da raiz do projeto vite.config.ts, pois é nele que definimos os arquivos que são gerados para uso como web components:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: [
{ find: '@', replacement: path.resolve(__dirname, './src') },
],
},
build: { //definimos configurações de build para geração dos web components
outDir: 'dist',
lib: {
entry: 'src/embed/templates-crud.tsx',
name: 'TemplatesCrudEmbed',
fileName: () => 'templates-crud-embed.js',
formats: ['umd'],
},
cssCodeSplit: false,
rollupOptions: {
external: [],
output: {
assetFileNames: (assetInfo) => {
if (assetInfo.name === 'style.css') return 'templates-crud-embed.css';
return assetInfo.name || 'assets/[name]-[hash][extname]';
},
},
}
},
define: {
'process.env.NODE_ENV': JSON.stringify('production')
}
});
Aplicando o Web Component
Para ser possível que utilizemos nosso componente TemplateCrud de forma distribuída, realizamos o build de nossa aplicação com o comando npm run build
Após, será criado o arquivo dist/templates-crud-embed.js. Podemos hospedá-lo em um CDN ou registrá-lo em algum repositório e integrarmos à pipeline do projeto principal. Para exemplificar seu uso, vamos mantê-lo em nosso sistema de arquivos e criar uma simples página html:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PoC - Sistema Host</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; background-color: #f4f4f9; }
.navbar { background: #333; color: white; padding: 15px; margin-bottom: 20px; }
.host-box { border: 2px solid #ccc; padding: 20px; background: white; }
</style>
<!-- 1. Importando o JS da sua "CDN" Local -->
<script src="./templates-crud-embed.js" defer></script>
</head>
<body>
<div class="navbar">
Menu App Externo
</div>
<div class="host-box">
<p>Web component:</p>
<templates-crud-microfrontend
api-url="<http://localhost:3001>"
bearer-token="123"
></templates-crud-microfrontend> </div>
</body>
</html>
Ao abrirmos nosso arquivo html, seremos contemplados com o carregamento do nosso web component:

Considerações Finais
É importante ressaltar que o projeto acima se trata de uma prova de conceito resumida. É importante que alguns padrões de segurança sejam levados em consideração ao aplicar e gerar web components para microfrontends. O primeiro deles é nunca expor tokens em propriedades HTML. Caso seja necessário transmissão de tokens entre a aplicação hospedeira e o web component, considere utilizar propriedades de classe Javascript.
A API utilizada pelo Web Component também não precisaria ser repassada como propriedade, mas, da mesma forma, é importante garantir a segurança do backend da aplicação hospedeira e do web components utilizando configurações de CORS e BFFs, já que requisições sempre são expostas no browser do usuário.
Você pode utilizar estratégias mais robustas para aplicar microfrontends em seus sistemas, uma delas é o module federation, que permite deploy separado de aplicações Javascript.
Integrar o build dos web components às pipelines do projeto é uma ótima forma de trabalhar o versionamento dos arquivos. É possível utilizar s3 com versionamentos de tags, em que cada tag gerada realiza um novo build e registra os arquivos na nuvem (v1.0/web-component.js, lts/web-component.js, etc.).
Para aplicar esse exemplo em aplicações que utilizam tailwind, a estratégia pode ser mantida com a adição de um novo arquivo chamado postcss.config.cjs. Dessa forma, conseguimos compilar todos os estilos em um arquivo css a parte, que pode ser utilizado em conjunto com os web components gerados.
Repositório do Projeto
https://github.com/Guilherme-Maciel/poc-mf-with-web-components
메타데이터
- post_id
- db7fb0c2d7ae
- slug
- arquitetura-de-interfaces-microfrontends-utilizando-web-components-db7fb0c2d7ae
- url
- https://medium.com/@guilherme5932.ms/arquitetura-de-interfaces-microfrontends-utilizando-web-components-db7fb0c2d7ae
- canonical_url
- https://medium.com/@guilherme5932.ms/arquitetura-de-interfaces-microfrontends-utilizando-web-components-db7fb0c2d7ae
- author_url
- https://medium.com/@guilherme5932.ms
- status
- ok
- fetched_at
- 2026-07-08 20:12:56