Voltar para o Blog
Anúncio

Microfrontends: A Arquitetura que Está Dominando Grandes Empresas em 2025

Olá HaWkers, você já trabalhou em uma aplicação frontend tão grande que mudanças simples viravam pesadelos? Deploys travavam tudo, times brigavam por conflitos de merge, e adicionar uma feature nova levava semanas?

Microfrontends surgiram exatamente para resolver esse problema, e em 2025 essa arquitetura finalmente atingiu maturidade suficiente para ser adotada em massa. Empresas como Spotify, IKEA, Zalando e American Express já migraram - e os resultados são impressionantes.

O Que São Microfrontends?

Pense em microfrontends como a aplicação de microservices no frontend. Em vez de um monolito gigante onde todo o código frontend vive em um único repositório, você divide a aplicação em pedaços menores, independentes e autônomos.

Cada microfrontend:

  • É desenvolvido por um time independente
  • Tem seu próprio repositório e pipeline de deploy
  • Pode usar tecnologias diferentes (React, Vue, Angular, Svelte)
  • É deployado independentemente dos outros
  • Compõe a aplicação final no browser ou servidor
Anúncio

Por Que Empresas Estão Migrando em Massa?

Os benefícios que estão convencendo CTOs ao redor do mundo:

1. Escalabilidade de Times

Com microfrontends, você pode ter 10 times trabalhando em paralelo sem pisarem uns nos pés dos outros. Cada time é dono de uma parte da aplicação.

2. Deploy Independente

Mudou o carrinho de compras? Deploy só dele. Não precisa fazer rebuild e redeploy da aplicação inteira. Isso reduz riscos e acelera entregas.

3. Tecnologia Flexível

Quer testar Vue em uma parte da app enquanto o resto usa React? Perfeitamente possível. Gradualmente migrar de Angular para React? Factível.

4. Resiliência

Se um microfrontend quebra, o resto da aplicação continua funcionando. Isolamento de falhas salva Black Fridays.

Implementando Microfrontends: Abordagens Principais

Existem várias formas de implementar microfrontends. Vamos explorar as 3 mais populares:

1. Module Federation (Webpack 5)

A abordagem mais moderna e poderosa. Webpack 5 permite compartilhar código entre aplicações em runtime:

// app-shell/webpack.config.js (Container principal)
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin');

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'appShell',
      remotes: {
        checkout: 'checkout@http://localhost:3001/remoteEntry.js',
        catalog: 'catalog@http://localhost:3002/remoteEntry.js',
        userProfile: 'userProfile@http://localhost:3003/remoteEntry.js',
      },
      shared: {
        react: { singleton: true, eager: true },
        'react-dom': { singleton: true, eager: true },
      },
    }),
  ],
};

// App.jsx - Consumindo microfrontends
import React, { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

// Lazy load microfrontends
const Checkout = lazy(() => import('checkout/CheckoutApp'));
const Catalog = lazy(() => import('catalog/CatalogApp'));
const UserProfile = lazy(() => import('userProfile/ProfileApp'));

function App() {
  return (
    <BrowserRouter>
      <div className="app-shell">
        <Header />
        <Suspense fallback={<div>Carregando...</div>}>
          <Routes>
            <Route path="/checkout/*" element={<Checkout />} />
            <Route path="/catalog/*" element={<Catalog />} />
            <Route path="/profile/*" element={<UserProfile />} />
          </Routes>
        </Suspense>
        <Footer />
      </div>
    </BrowserRouter>
  );
}
Anúncio

2. Single-SPA

Framework agnóstico que permite orquestrar múltiplos frameworks:

// root-config.js
import { registerApplication, start } from 'single-spa';

// Registrar microfrontends de diferentes frameworks
registerApplication({
  name: '@company/react-app',
  app: () => System.import('@company/react-app'),
  activeWhen: ['/react'],
});

registerApplication({
  name: '@company/vue-app',
  app: () => System.import('@company/vue-app'),
  activeWhen: ['/vue'],
});

registerApplication({
  name: '@company/angular-app',
  app: () => System.import('@company/angular-app'),
  activeWhen: ['/angular'],
});

start({
  urlRerouteOnly: true,
});

// Cada microfrontend exporta lifecycle functions
// react-app/src/root.component.js
import React from 'react';
import ReactDOM from 'react-dom';
import singleSpaReact from 'single-spa-react';
import Root from './Root.component';

const lifecycles = singleSpaReact({
  React,
  ReactDOM,
  rootComponent: Root,
  errorBoundary(err, info, props) {
    return <div>Ops! Erro no microfrontend React.</div>;
  },
});

export const { bootstrap, mount, unmount } = lifecycles;

3. Web Components

Abordagem usando padrões web nativos:

// checkout-microfrontend/checkout-widget.js
class CheckoutWidget extends HTMLElement {
  connectedCallback() {
    this.render();
    this.attachEventListeners();
  }

  render() {
    this.innerHTML = `
      <div class="checkout-container">
        <h2>Checkout</h2>
        <div id="cart-items"></div>
        <button id="complete-purchase">Finalizar Compra</button>
      </div>
    `;
  }

  attachEventListeners() {
    const button = this.querySelector('#complete-purchase');
    button.addEventListener('click', () => {
      this.dispatchEvent(new CustomEvent('purchase-completed', {
        detail: { total: this.calculateTotal() },
        bubbles: true,
      }));
    });
  }

  calculateTotal() {
    // Lógica de cálculo
    return 199.90;
  }
}

customElements.define('checkout-widget', CheckoutWidget);

// app-shell/index.html
<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.checkout.com/widget.js"></script>
  </head>
  <body>
    <app-header></app-header>
    <checkout-widget></checkout-widget>
    <app-footer></app-footer>

    <script>
      document.addEventListener('purchase-completed', (e) => {
        console.log('Compra finalizada:', e.detail.total);
        analytics.track('Purchase', { total: e.detail.total });
      });
    </script>
  </body>
</html>
Anúncio

Comunicação Entre Microfrontends

Um dos desafios mais críticos: como microfrontends se comunicam?

1. Event Bus Global

// shared-event-bus.js
class EventBus {
  constructor() {
    this.events = {};
  }

  subscribe(eventName, callback) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);

    // Retorna função de unsubscribe
    return () => {
      this.events[eventName] = this.events[eventName].filter(
        cb => cb !== callback
      );
    };
  }

  publish(eventName, data) {
    if (!this.events[eventName]) return;
    this.events[eventName].forEach(callback => callback(data));
  }
}

export const eventBus = new EventBus();

// No microfrontend A
import { eventBus } from '@shared/event-bus';

function addToCart(product) {
  // Lógica local
  cart.add(product);

  // Notificar outros microfrontends
  eventBus.publish('cart:updated', {
    itemCount: cart.getItemCount(),
    total: cart.getTotal(),
  });
}

// No microfrontend B (header com contador de carrinho)
import { eventBus } from '@shared/event-bus';

function CartCounter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const unsubscribe = eventBus.subscribe('cart:updated', (data) => {
      setCount(data.itemCount);
    });

    return unsubscribe;
  }, []);

  return <div className="cart-icon">{count}</div>;
}

2. Shared State Management

// shared-store/cart-store.js
import create from 'zustand';

// Store compartilhado entre microfrontends
export const useCartStore = create((set, get) => ({
  items: [],
  total: 0,

  addItem: (item) => set((state) => {
    const items = [...state.items, item];
    return {
      items,
      total: items.reduce((sum, i) => sum + i.price, 0),
    };
  }),

  removeItem: (itemId) => set((state) => {
    const items = state.items.filter(i => i.id !== itemId);
    return {
      items,
      total: items.reduce((sum, i) => sum + i.price, 0),
    };
  }),

  getItemCount: () => get().items.length,
}));

// Qualquer microfrontend pode usar
import { useCartStore } from '@shared/cart-store';

function ProductCard({ product }) {
  const addItem = useCartStore(state => state.addItem);

  return (
    <div>
      <h3>{product.name}</h3>
      <button onClick={() => addItem(product)}>
        Adicionar ao Carrinho
      </button>
    </div>
  );
}
Anúncio

Quando NÃO Usar Microfrontends

Microfrontends não são bala de prata. Evite se:

  1. Time pequeno: Se você tem menos de 3 times, o overhead não compensa
  2. Aplicação simples: Landing pages ou dashboards simples não precisam
  3. Falta de DevOps maduro: Precisa de CI/CD sólido e infraestrutura para orquestrar múltiplos deploys
  4. Performance crítica: Overhead de carregar múltiplos bundles pode impactar
  5. Startup early-stage: Premature optimization. Foque em product-market fit primeiro

Desafios Reais e Como Superá-los

1. Duplicate Dependencies

Problema: Cada microfrontend carrega React, resultando em 3x o bundle size.

Solução: Module Federation com shared dependencies:

shared: {
  react: { singleton: true, requiredVersion: '^18.0.0' },
  'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
}

2. Styling Conflicts

Problema: CSS de um microfrontend vazando para outro.

Solução: CSS Modules, CSS-in-JS (styled-components), ou Shadow DOM.

3. Consistência de UX

Problema: Cada time criando componentes diferentes do zero.

Solução: Design System compartilhado com Storybook.

Casos de Sucesso Reais

Spotify: Reduziu tempo de build de 45min para 5min após migração para microfrontends.

IKEA: 30 times autônomos deployando independentemente, aumento de 3x na velocidade de entregas.

Zalando: Resiliência melhorou 90% - falhas isoladas não afetam toda a aplicação.

Se você está interessado em arquiteturas modernas e escaláveis, recomendo também: Serverless em 2025: Node.js e a Arquitetura Sem Servidor que explora outra tendência complementar aos microfrontends.

Bora pra cima! 🦅

🎯 Domine as Bases para Trabalhar com Arquiteturas Avançadas

Microfrontends são poderosos, mas exigem fundamentos sólidos de JavaScript, módulos, e arquitetura.

Se você quer estar preparado para trabalhar em projetos de grande escala:

Invista no seu conhecimento:

  • 3x de R$34,54 no cartão
  • ou R$97,90 à vista

🚀 Acessar Guia Completo

"Base sólida que me preparou para trabalhar com arquiteturas complexas!" - Ana, Senior Frontend

Anúncio
Post anteriorPróximo post

Comentários (0)

Esse artigo ainda não possui comentários 😢. Seja o primeiro! 🚀🦅

Adicionar comentário