Decision tree, futuro e entrevista

TL;DR

O ecossistema de tooling JS/TS está em um ponto de inflexão: o modelo “muitas ferramentas especializadas” está cedendo para “poucos toolchains unificados em Rust”. Vite 8 + Rolldown (produção, março/2026) unificou dev e prod num único motor. Biome 2.x e oxlint 1.0 (junho/2025) tornam lint + format uma decisão binária. Bun consolidou sua posição como all-in-one. E a Cloudflare adquiriu a VoidZero em junho/2026, apostando que o futuro do tooling é inseparável do runtime da web. Para entrevistas seniores, o que importa não é decorar flags — é articular o porquê de cada escolha, em inglês, com raciocínio de trade-offs.

Esta é a nota CAPSTONE da trilha. As 25 notas anteriores carregam o lastro; aqui costuramos tudo em três entregáveis concretos: (1) uma árvore de decisão para escolher a ferramenta certa por tipo de projeto, (2) um mapa do futuro do ecossistema com o que já aconteceu em 2026, e (3) um bloco de entrevista com perguntas reais, respostas-modelo e vocabulário técnico em inglês.


1. A tese da trilha

Tooling existe porque há um gap entre o que você escreve (ESM, TypeScript, JSX, CSS moderno, dependências externas) e o que roda (JavaScript compatível, otimizado, empacotado, entregue). O pipeline resolver → transpilar → empacotar → otimizar → servir é a espinha da trilha, e cada ferramenta que estudamos vive em algum ponto desse eixo.

A trajetória histórica — de scripts inline a task runners a bundlers a dev servers com ESM nativo — não é nostalgia: é o mapa de decisão. Entender por que cada geração nasceu explica quando cada ferramenta ainda faz sentido.

A tese central que um sênior precisa articular:

Ferramenta de build certa é aquela que fecha o seu gap específico com o menor custo de manutenção. Velocidade importa; corretude importa mais; a curva de evolução da equipe importa tanto quanto os dois.


2. Árvore de decisão — que ferramenta pra que projeto

O diagrama abaixo responde a pergunta “por onde começar” dado o tipo de projeto. Não é prescritivo no nível de configuração — é a árvore de entrada para chegar à ferramenta certa antes de ler a doc.


flowchart TD
    Start(["Novo projeto\n— por onde começar?"])

    Start --> Q1{"Qual é o artefato\nfinal?"}

    Q1 -->|"App rodando\nno browser"| Q2{"Qual framework\nou stack?"}
    Q1 -->|"Biblioteca\npara publicar no npm"| Lib
    Q1 -->|"App CLI / backend\nNode ou Bun"| Q_CLI
    Q1 -->|"Monorepo\n(múltiplos pacotes)"| Mono

    Q2 -->|"React / Vue / Svelte\nprojeto novo"| Vite["✅ Vite 8\n(Rolldown nativo)\nscaffold: npm create vite@latest"]
    Q2 -->|"Next.js / Nuxt / SvelteKit"| Meta["✅ Meta-framework\n(Next/Nuxt/SvelteKit)\nusam Vite ou Turbopack internamente;\nnão configure bundler separado"]
    Q2 -->|"Projeto legado\nwebpack já em produção"| LegacyApp{"Vale migrar?"}
    LegacyApp -->|"Sim — timeline disponível"| Rspack["🔄 Rspack como\nbridge de migração\n(drop-in webpack)"]
    LegacyApp -->|"Não — custo alto\nou módulos webpack-específicos"| Webpack["⚠️ webpack 5\ncom Module Federation;\nmantém mas não expande"]

    Lib --> Q_Lib{"Precisa de dual\nESM + CJS?"}
    Q_Lib -->|"Sim (lib para npm amplo)"| Rollup["✅ Rollup 4\nou tsdown (VoidZero)\nmelhor tree-shaking para libs"]
    Q_Lib -->|"Não / ESM only"| EsbuildLib["✅ tsdown (DTS nativo)\nou esbuild se DTS\nnão é necessário"]

    Q_CLI --> Q_CLItype{"Precisa de\nbundler CLI?"}
    Q_CLItype -->|"Não — só rodar TS"| Runtime["✅ Node + tsx\nou Bun (nativo)"]
    Q_CLItype -->|"Sim — empacotar\nem único executável"| SEA["✅ esbuild / ncc\n+ Node SEA\nou Bun --compile"]

    Mono --> Q_Mono{"Qual é a escala?"}
    Q_Mono -->|"Pequeno/médio\n< 20 pacotes"| PnpmWork["✅ pnpm workspaces\n+ Vite por app"]
    Q_Mono -->|"Grande / CI precisa\nde cache incremental"| Turbo["✅ Turborepo\n(task cache + pipeline)\ncom pnpm workspaces"]
    Q_Mono -->|"Enterprise / escala\nde centenas de pacotes"| Nx["✅ Nx\n(plugin ecosystem\naffected builds)"]

    subgraph Qualidade["Camada de qualidade — independente do bundler"]
        direction LR
        Q_Lint{"Projeto novo\nou legado?"}
        Q_Lint -->|"Novo — zero config"| Biome2["Biome 2.x\n(lint + format, zero config)"]
        Q_Lint -->|"Novo — quer máx performance"| Oxlint1["oxlint 1.0\n+ oxfmt (beta)\n(mais rápido, menos regras)"]
        Q_Lint -->|"Legado com ESLint\nconfigurações extensas"| ESLintHybrid["ESLint (manter)\n+ oxlint como camada\nde pré-check mais rápida"]
    end

    Vite -.-> Qualidade
    Rollup -.-> Qualidade
    Mono -.-> Qualidade

Leitura do diagrama

As setas sólidas são decisões de bundler/framework. As setas tracejadas lembram que a camada de qualidade (lint/format) é ortogonal — você escolhe Biome, oxlint ou ESLint independentemente do bundler escolhido acima.

Por que tsdown para libs ESM-only — e não esbuild direto?

A árvore lista esbuild bundler ou tsdown para libs ESM-only. A distinção importa: esbuild não gera .d.ts nativamente — exige um passo separado com tsc --emitDeclarationOnly, o que adiciona configuração e um segundo processo de build. Para qualquer lib publicada no npm com TypeScript, tipos não são opcionais. tsdown — baseado em Rolldown, parte do ecossistema VoidZero — tem geração de DTS nativa via isolatedDeclarations, zero config, e dual ESM+CJS automático. Use esbuild direto apenas em ferramentas internas ou scripts onde você controla o consumidor e tipos não são necessários. Para libs npm, tsdown é a escolha com menor custo de manutenção.

Quando cada ferramenta ganha

CenárioFerramentaMotivo principal
SPA novo (React/Vue/Svelte)Vite 8HMR em ESM nativo, Rolldown unificado, ecossistema maduro
Meta-framework (Next/Nuxt)bundler internoNext usa Turbopack; Nuxt usa Vite; não configure manualmente
Lib para npmRollup 4 / tsdownTree-shaking superior; dual ESM+CJS sem gambiarras
Migração de webpack legadoRspackDrop-in replacement; não quebra plugins webpack
Monorepo médiopnpm + TurborepoCache incremental simples, curva baixa
Monorepo enterpriseNxAffected builds, grafo de dependências, plugin ecosystem
CLI / script Nodetsx ou BunZero config; Bun roda TS nativo sem transpilação
Qualidade greenfieldBiome 2.xZero config, zero deps externas, lint + format em um

3. O futuro do ecossistema — o que já aconteceu em 2026

3.1 Linha do tempo consolidada


timeline
    title Marcos do tooling JS/TS — 2023→2026
    2023 : Bun 1.0 GA — runtime all-in-one (set/2023)
         : VoidZero fundada por Evan You — aposta no toolchain unificado
    2024 : Rolldown alpha — futuro motor do Vite
         : oxlint beta — linter Rust 50× mais rápido que ESLint
         : Vite 5 estável
    2025 : Biome 2.x GA — lint + format zero-config (jun/2025)
         : oxlint 1.0 GA — linter Rust de produção (jun/2025)
         : Rolldown 1.0 GA — bundler Rust pronto para produção (mai/2025)
         : Vite 7 — target baseline widely available, ESM only
    2026 : Vite 8 GA — Rolldown como motor unificado (mar/2026)
         : rolldown-vite arquivado — Rolldown é o Vite
         : Cloudflare adquire VoidZero — jun/2026
         : Vite+ alpha — toolchain unificado (runtime + pkg + build)
         : oxfmt beta — formatter Rust 35× mais rápido que Prettier

3.2 Vite 8 + Rolldown — o fim da dualidade dev/prod

O problema histórico do Vite era ter dois motores: esbuild no dev server (rápido, ESM nativo) e Rollup na produção (mais lento, mas com melhor tree-shaking e plugin ecosystem). Essa dualidade causava bugs reais — comportamentos diferentes de resolução de módulos, tree-shaking, e circular deps entre dev e prod.

Vite 8 (março/2026) resolveu isso: Rolldown é o motor único. O dev server e o build de produção usam o mesmo grafo de módulos, as mesmas regras de resolução, os mesmos plugins. A classe inteira de “funciona no dev, quebra em prod” desapareceu.

O ganho de performance: builds de produção 4–20× mais rápidos que Rollup. Rolldown é na faixa de performance do esbuild, mas com a compatibilidade de plugins do Rollup.

O range é amplo porque duas variáveis dominam em direções opostas:

  • Número de módulos e tamanho do grafo: projetos com centenas de módulos ganham mais do paralelismo Rust — o overhead de serialização do Rollup JS cresce linearmente com o grafo. Um projeto com 500+ módulos tende ao extremo de 10–20×.
  • Plugins JS pesados: cada plugin Vite/Rollup escrito em JavaScript introduz um salto de contexto entre o runtime Rust e o V8. Projetos com muitos plugins JS (transforms de SVG, Workers com config manual, codemods em plugin) ficam próximos do 4× porque o gargalo se torna a camada JS, não o bundler em si.

Para a decisão prática: projetos novos, greenfield, com poucos plugins → espere o extremo superior. Projetos com plugin ecosystem pesado herdado → o ganho real fica na faixa de 4–6×, ainda significativo, mas não revolucionário.

Referência: 14 - Rollup, esbuild e Rolldown.

3.3 A corrida Rust/Go e o toolchain unificado

A tendência de reescrever ferramentas JS em Rust ou Go — que estudamos em 15 - Turbopack, Rspack e a corrida Rust-Go — atingiu maturidade em 2026. O padrão emergente não é mais “ferramenta isolada em Rust” mas toolchain unificado:

VoidZero / Vite+: o binário vp combina Vite 8 + Vitest + oxlint + oxfmt + Rolldown + tsdown em um único zero-config entrypoint com task runner nativo (Vite Task), caching integrado e suporte a monorepo. A aquisição pela Cloudflare (junho/2026) colocou muscle financeiro atrás do projeto, com compromisso público de manter MIT e vendor-agnostic. Performance reportada: oxlint 50–100× mais rápido que ESLint; oxfmt até 30× mais rápido que Prettier. Fonte: VoidZero — Announcing Vite+.

OXC (oxc-project): a ambição é um toolchain completo — parser, linter, formatter, minifier, transformer — todos em Rust, todos integrados. Em 2026: oxlint 1.0 (produção), oxfmt beta, minifier e transformer em progresso. A vantagem arquitetural: quando todos os componentes compartilham o mesmo AST Rust, elimina-se a serialização/desserialização entre etapas — o parser produz um AST que o linter, formatter e bundler consomem diretamente.

Bun: continua sua aposta de ser tudo — runtime, package manager, test runner, bundler, e runtime TypeScript nativo. Na versão 1.3.x (2026): production-grade, usado em produção por projetos reais.

Vite+ em uma linha

npm create vite-plus@latest → projeto com Vite + Vitest + oxlint + oxfmt + Rolldown configurados e integrados. Zero decisões de tooling para um projeto novo greenfield em 2026.

3.4 Biome e oxlint — o fim do duopólio ESLint + Prettier

Em 2025–2026, a pergunta deixou de ser “ESLint ou Prettier?” e passou a ser “Biome ou oxlint?“. Os dois são Rust, os dois são ordens de magnitude mais rápidos. A diferença prática:

CritérioBiome 2.xoxlint 1.0 + oxfmt (beta)ESLint + Prettier
Performance (lint)Muito rápido2× mais rápido que BiomeLinha de base
Performance (format)Muito rápido3× mais rápido que Biome, 35× que PrettierLinha de base
Regras de lint~200~500 curadas (alta relação sinal/ruído, baixo falso-positivo)+1000 (via plugins)
Por que menos regras pode ser vantagemESLint com plugins acumula regras que, em produção, geram ruído — o time começa a ignorar o linter. Biome e oxlint selecionam regras com alta relação sinal/ruído: cobrem os erros que realmente causam bugs, com taxa de falso-positivo baixa. Estilo fica para o formatter.
Plugin ecosystemCrescendoJS plugins alpha (2026)Maduro e vasto
Config necessáriaZeroZeroAlta (sem preset)
DependênciasZeroZeroMúltiplas
MaturidadeGA desde 2024GA 1.0 jun/2025Maturíssimo
Quando usarGreenfield, DX máximaGreenfield, velocidade máxima; ou como camada sobre ESLintLegado, plugins críticos

Referência: 16 - Linting, formatting e git hooks.

3.5 IA no tooling — o que mudou

25 - IA no tooling e build é a nota dedicada; aqui o resumo executivo para entrevista:

A IA entrou no tooling em três camadas:

  1. Geração de configuração: vite.config.ts, .eslintrc, tsconfig.json são rotineiramente gerados por LLMs — o dev precisa entender o que gerou, não como digitar.
  2. Análise de bundle: ferramentas como Cursor IDE e plugins de IA visualizam bundle analyzer e sugerem lazy loading / code splitting automaticamente.
  3. Codemod automatizado: migrar de CRA para Vite, de CommonJS para ESM, de Prettier para Biome — LLMs geram os scripts de migração. O dev valida; não precisa mais escrever do zero.

Para entrevistas: o senior não defende “IA é boa” ou “IA é ruim” — ele articula em que partes do pipeline a IA já tem alta confiabilidade (config, boilerplate, migrate scripts) e onde ainda precisa de revisão crítica (configuração de otimização, análise de bundle de produção, decisões de trade-off).


4. Comparativos rápidos para entrevista

npm vs pnpm vs Bun (package manager)

npmpnpmBun
Modelo de armazenamentoflat node_modulescontent-addressable store + hard linksCache similar ao pnpm
VelocidadeLinha de base2–3× npm4–10× npm
Disk usageAlto (duplica deps)Baixo (hard links)Baixo
Monorepo workspaces✅ (melhor isolamento)
Phantom depsSim (flat)Não (strict)Não
Quando usarDefault simplesMonorepos, strictnessProjetos Bun-first, CLIs

Referência: 03 - Package managers - npm, pnpm, yarn e Bun.

Vite vs webpack (a pergunta garantida de entrevista)

Vite 8webpack 5
Dev serverESM nativo — módulos servidos pelo browser, sem bundleBundle incremental + HMR
HMR~87ms mediana~2.1s mediana (2026)
Build produçãoRolldown (Rust, unificado)webpack + loaders
Plugin ecosystemRolldown-compat + Vite pluginsVasto (loaders/plugins maduros)
Module FederationPlugin disponível (maturing)MF v1 e v2 — mais maduro
Config complexityBaixaAlta
Quando usarProjetos novos, praticamente tudoLegado, Module Federation complexo

ESM vs CJS — a distinção que aparece toda entrevista

CJS: require() — síncrono, runtime, opaco para bundler
ESM: import   — estático, compile-time, analisável para tree-shaking

Tree-shaking só funciona com ESM — o bundler precisa saber em
compile time quais exports são usados. CJS é caixa preta.

Interop em 2026: funciona, mas tem custo. pnpm com
node_modules legado = CJS. Libs modernas: "exports" no
package.json com dual ESM+CJS.

Referência: 06 - ESM e CJS e o sistema de módulos.


5. Perguntas de entrevista — respostas-modelo

”Explique a diferença entre dev server e build de produção no Vite.”

Em dev, o Vite serve os módulos diretamente via ESM nativo — o browser faz os imports, o servidor não empacota nada. Isso é o que torna o HMR tão rápido: apenas o módulo alterado é revalidado. Em produção, o Vite usa Rolldown (desde a versão 8) para empacotar tudo: aplica tree-shaking, code splitting, minificação, e gera assets com hash para cache de longa duração. A arquitetura é intencionalmente diferente nos dois modos porque os objetivos são opostos — dev quer feedback instantâneo; produção quer tamanho mínimo e entrega otimizada.

Frase EN: “In dev, Vite serves raw ES modules — the browser handles the imports, so there’s nothing to bundle. In production, Rolldown kicks in: it resolves the full module graph, applies tree-shaking, code splitting, and minification. Vite 8 unified both modes under Rolldown, which eliminated an entire class of dev/prod divergence bugs.”


”O que é tree-shaking e por que ele exige ESM?”

Tree-shaking é a eliminação de código não usado (dead code) durante o bundle. Para funcionar, o bundler precisa analisar estaticamente quais exports são consumidos antes de executar qualquer código. ESM permite isso porque os import e export são declarações estáticas — o bundler sabe o grafo completo em tempo de compilação. CommonJS é dinâmico (require(someVariable)), então o bundler não pode determinar em compile time quais partes são usadas — precisa incluir tudo.

Frase EN: “Tree-shaking requires ESM because ESM imports are static declarations — the bundler knows the complete dependency graph at compile time without executing anything. CommonJS uses dynamic require() calls, so the bundler can’t statically determine what’s used and has to include everything.”

Referência: 17 - Otimização de bundle.


”Quando você usaria webpack em 2026?”

Para projetos novos: praticamente nunca. Vite tem DX superior, performance melhor, e o plugin ecosystem madurou. Mas webpack ainda ganha em dois cenários concretos: (1) Module Federation complexo — quando você tem micro-frontends em produção com compartilhamento de dependências em runtime, a implementação madura do MF v2 do webpack ainda é mais robusta; (2) migração de legado — bases de código grandes com loaders webpack específicos (imagens, SVG com transforms, workers configurados a mão) levam tempo para migrar. Nesses casos, Rspack (drop-in replacement em Rust) é o caminho de menor risco: mesma API, 5–10× mais rápido.

Frase EN: “Webpack is the right choice when you have Module Federation at scale — it has the most mature MF implementation. And for large legacy codebases, Rspack is the pragmatic bridge: drop-in webpack API, Rust performance, no plugin rewrites. But for new projects, there’s no good reason not to use Vite 8."


"Por que pnpm em monorepo em vez de npm?”

pnpm resolve o problema de phantom dependencies — quando você usa um pacote que está no node_modules mas que não está no seu package.json, só porque outro pacote o instalou como dependência transitiva. npm (com flat node_modules) faz isso silenciosamente; pnpm cria uma estrutura com symlinks onde cada pacote só acessa o que declarou explicitamente. Em monorepos, isso é crítico: sem o isolamento do pnpm, pacotes do workspace podem silenciosamente depender uns dos outros sem declarar. O segundo motivo é espaço: pnpm usa um content-addressable store global com hard links — a mesma versão de uma dep é armazenada uma vez, não uma vez por pacote.

Frase EN: “pnpm solves phantom dependencies — in a flat node_modules layout, you can require a package that’s not in your package.json because it’s a transitive dep of something else. pnpm uses a strict symlink structure so each package can only access what it explicitly declared. For monorepos, that strictness is essential. The disk savings from the global store are a bonus."


"O que é HMR e como funciona no Vite?”

HMR (Hot Module Replacement) é a atualização de um módulo no browser sem recarregar a página inteira. No Vite, o dev server mantém uma conexão WebSocket com o browser. Quando um arquivo muda, o servidor invalida apenas aquele módulo e seus dependentes diretos no grafo, e envia uma mensagem ao browser com o módulo atualizado.

A preservação de estado não é automática — ela depende do módulo registrar um handler na HMR API (import.meta.hot.accept). Frameworks como React (via React Fast Refresh) e Vue fazem isso automaticamente para componentes: os plugins Vite injetam os handlers durante a transpilação, por isso os componentes React e Vue atualizam sem perder estado de formulário, scroll ou dados locais. Mas um módulo utilitário sem handler registrado dispara um full reload quando alterado — o Vite não tem como saber se o novo valor é compatível com o estado atual do app.

A velocidade vem do escopo: o Vite nunca rebundla a aplicação inteira — só revalida o subgrafo do módulo alterado.

Frase EN: “HMR works through a WebSocket connection between the dev server and the browser. When a file changes, Vite invalidates just that module and its direct dependents in the module graph, then sends the updated module to the browser. State preservation depends on the module implementing the HMR API — React Fast Refresh and Vue’s HMR plugin inject those handlers automatically for components. A plain utility module without a handler triggers a full reload. The speed comes from scope: Vite never re-bundles the whole app, only the affected subgraph.”

Referência: 09 - Dev server e HMR.


”O que é code splitting e quando você o usa?”

Code splitting é dividir o bundle final em múltiplos chunks que são carregados sob demanda, em vez de um único bundle gigante que o browser precisa baixar e parsear inteiro antes de renderizar qualquer coisa. O caso de uso principal é roteamento: cada rota recebe seu próprio chunk, carregado apenas quando o usuário navega até ela. O segundo caso é componentes pesados que não aparecem na tela imediatamente (modais, dashboards avançados, editores rich text). Em Vite/Rolldown, code splitting automático já é aplicado para imports dinâmicos (import()); o desenvolvedor controla manualmente via React.lazy ou defineAsyncComponent no Vue.

Frase EN: “Code splitting divides the bundle into chunks loaded on demand. The browser only downloads what’s needed for the initial route, then lazily fetches the rest. I use dynamic imports (await import('./HeavyComponent')) at route boundaries and for components that aren’t on the critical rendering path. Rolldown/Vite handles the chunk graph automatically — I just mark the split points."


"O que é o pipeline de tooling e onde cada ferramenta se encaixa?”

Código fonte
    ↓ [resolver] — onde está cada módulo? (Node resolution, exports, conditions)
    ↓ [transpilar] — TS→JS, JSX→JS, ESNext→ES compatível (esbuild/SWC/Babel)
    ↓ [empacotar] — une os módulos num grafo (Rolldown/webpack/Rollup)
    ↓ [otimizar] — tree-shaking, minify, split, hash (Rolldown/Terser)
    ↓ [servir] — CDN/servidor/filesystem

Cada fase tem ferramentas especializadas, mas os bundlers modernos (Vite/webpack) integram todas. Entender as fases separadamente permite diagnosticar onde um problema está: se imports quebram é o resolver; se o output tem código legado inesperado é o target da transpilação; se o bundle está grande é tree-shaking ou code splitting.

Referência: 01 - Por que tooling e build existem, 07 - O grafo de módulos e o que é bundling, 08 - Transpilação e targets.


6. Como explicar em inglês

Parágrafos-modelo calibrados para entrevista. Primeira pessoa, postura técnica — não relato de projeto.

Modern JavaScript tooling solves a fundamental gap: what you write — TypeScript, ESM, JSX, modern CSS, third-party dependencies — and what runs in production — optimized, bundled, compatible JavaScript — are very different things. The entire build pipeline exists to close that gap. Understanding each stage — resolve, transpile, bundle, optimize, serve — is what lets me diagnose problems precisely instead of just rerunning the build and hoping.

I default to Vite 8 for new browser-targeted projects. The key insight is that its dev server and production build now share the same engine — Rolldown — which eliminates an entire class of bugs that came from dev using esbuild and prod using Rollup. Different module resolution rules meant code that worked in dev silently broke in production. Vite 8 solved that structurally.

For libraries published to npm, I reach for Rollup or tsdown rather than Vite. Libs need dual ESM and CJS output with precise control over what’s bundled versus externalized. Rollup’s tree-shaking is purpose-built for that use case — you want the consumer’s bundler, not yours, to do the final dead-code elimination.

In monorepos, the question is usually “do I need task orchestration or just workspaces?” For most teams, pnpm workspaces plus Turborepo is the right answer — pnpm gives strict dependency isolation, Turbo adds build caching with a simple pipeline definition. Nx makes sense at enterprise scale when you need affected-only builds across hundreds of packages and a richer plugin model.

On linting and formatting: I’ve moved to Biome for new projects. It’s lint and format in one binary, zero configuration, zero external dependencies, and it’s orders of magnitude faster than ESLint plus Prettier. For existing projects where ESLint has extensive custom rules, I keep ESLint and layer oxlint on top as a fast pre-check — it catches the common issues instantly, and ESLint handles the project-specific rules.

The most important thing I’ve learned about build tooling is that configuration complexity is a cost, not a feature. The ideal is a tool that works correctly with zero config and lets you opt into complexity when your use case genuinely requires it. That’s the direction the ecosystem has moved — Vite, Biome, Bun, Rolldown are all designed around that principle.

When it comes to system design questions around CI build performance, my frame is always: measure first, parallelize second, cache third. The common mistake is adding caching before you understand which steps are actually slow. Once you have visibility, parallelize the independent steps — typecheck, lint, and test can usually run concurrently. Then add remote caching — in a monorepo, Turborepo’s remote cache with affected-only task runs is the biggest single lever. Only after those do you look at replacing tools — switching from Jest to Vitest, or from ESLint to oxlint, gives real wins but requires migration effort.

On module federation in 2026: MF2 changed the picture significantly. It’s no longer a webpack-exclusive concern — the @module-federation/enhanced package works across webpack, Rspack, Vite, and Rollup with a unified runtime. For teams doing micro-frontends, MF2 on Rspack is the pragmatic path: you get webpack API compatibility, Rust-level build performance, and MF2’s type-sharing and manifest-based host discovery.


7. Vocabulário-chave PT→EN consolidado

PortuguêsEnglish
pipeline de buildbuild pipeline
empacotador / bundlerbundler
grafo de módulosmodule graph
resolução de módulosmodule resolution
transpilaçãotranspilation / transpiling
downlevelingdownleveling
árvore de dependênciasdependency tree
agitação de árvoretree-shaking
divisão de códigocode splitting
carregamento sob demandalazy loading / on-demand loading
substituição de módulo quentehot module replacement (HMR)
servidor de desenvolvimentodev server
minificaçãominification / minifying
mapa de fontesource map
rastreamento de conteúdocontent hashing
cache de longa duraçãolong-term caching
efeito colateralside effect
dependência fantasmaphantom dependency
gerenciador de pacotespackage manager
armazenamento de conteúdo endereçávelcontent-addressable store
hard linkhard link
versão de semânticasemantic versioning / semver
arquivo de travamentolockfile
escoposcope / workspace
espaço de trabalhoworkspace
monorepomonorepo
orquestração de tarefastask orchestration
build incrementalincremental build
build afetadoaffected build
cacheamento de tarefastask caching
execução única de aplicativosingle executable application (SEA)
ferramenta de qualidadequality tooling
lintagemlinting
formataçãoformatting
hook de gitgit hook
alvo de compilaçãocompilation target
polyfillpolyfill
shimshim
compilação cruzadacross-compilation
camada de compatibilidadecompatibility shim / compat layer
resolução de módulosmodule resolution
mapa de exportaçõesexports map
condição de exportaçãoexport condition
dependência transitivatransitive dependency
dependência parpeer dependency
dependência aninhadanested dependency
empacotamento de executávelexecutable bundling
análise estáticastatic analysis
árvore de chamadascall tree
grafo de dependênciasdependency graph
arquivo de manifestomanifest file
linha de base amplamente disponívelwidely available baseline
efeito colateral de importaçãoimport side effect
declaração de tipotype declaration / .d.ts
inferência de tipotype inference
modo estritostrict mode
registro de pacotespackage registry
assinatura de proveniênciaprovenance attestation
lista de materiais de softwaresoftware bill of materials (SBOM)
build distribuídodistributed build
build afetadoaffected build
grafo de tarefastask graph
cache de artefatoartifact cache
paralelismo de tarefastask parallelism

8. Red flags e green flags na entrevista

Red flags — o que sinaliza nível júnior/pleno em papel sênior

  • “Vite é mais rápido que webpack” sem explicar por quê — a resposta rasa. O entrevistador quer ouvir: “Vite serve ESM nativo no dev, então o browser faz os imports e não há bundle no dev server — o HMR revalida só o módulo alterado, não a aplicação inteira.”
  • Confundir transpilação com bundling — “o Babel empacota o código” está errado. Babel transforma; o bundler empacota. São etapas diferentes do pipeline. Ver 08 - Transpilação e targets.
  • “Tree-shaking remove código desnecessário” sem mencionar ESM — tree-shaking é análise estática de grafo de importações; só funciona com ESM estático. Libs que usam CJS não podem ter tree-shaking aplicado.
  • “pnpm é mais rápido que npm” sem explicar o modelo de armazenamento — a velocidade é consequência do content-addressable store com hard links; o benefício real para monorepos é o isolamento de phantom dependencies.
  • Não saber o que é code splitting — ou saber a definição mas não saber como aplicar (dynamic import, React.lazy, route-based splitting).
  • “Não uso monorepo porque é complicado” sem alternativa — sênior articula quando monorepo vale o custo e quando não vale.
  • Não ter opinião sobre lint/format — em 2026, “eu uso ESLint com a config padrão” sem saber Biome ou oxlint sinaliza que não acompanhou o ecossistema.

Green flags — o que impressiona

  • Articular o pipeline completo — resolver → transpilar → empacotar → otimizar → servir, e encaixar cada ferramenta na fase certa.
  • Explicar por que Vite tem dois modos e o que Vite 8 resolveu ao unificá-los — mostra que você entende o problema, não só a solução.
  • Mencionar phantom dependencies ao explicar pnpm — mostra que você pensa em corretude, não só em performance.
  • Citar Module Federation ao falar de webpack — sinaliza que você conhece o caso de uso legítimo, não só o legado.
  • Distinguir Rolldown de Rollup de esbuild — são três ferramentas diferentes com trade-offs diferentes; confundir as três é red flag; articulá-las é green flag.
  • Ter opinião fundamentada sobre Biome vs oxlint — não é “uma é melhor”; é “Biome tem mais regras e melhor DX; oxlint é mais rápido e tem JS plugin API chegando — para legados com ESLint, oxlint como camada é o caminho.”
  • Falar sobre supply chainnpm audit, lockfiles, provenance, SBOM. Ver 24 - Supply chain e segurança de dependências. Mostra que você pensa em produção, não só em DX.
  • Mencionar determinismo no CI — builds determinísticos, lockfiles commitados, pinning de versões, reproducible builds. Ver 23 - Build em produção, CI e determinismo.
  • Citar tsdown para bibliotecas — saber que existe uma camada acima do Rolldown, otimizada para autores de biblioteca, com geração de DTS nativa, é um sinal de atualização do ecossistema.
  • Saber quando NÃO usar Vite — em apps com milhares de módulos onde o cold start importa mais que o HMR, Turbopack ou bundling incremental pode ser melhor escolha. Saber a exceção é tão importante quanto saber a regra.
  • Articular Module Federation 2.0 — não só “webpack tem MF”; saber que MF2 funciona em Vite, Rspack e webpack via @module-federation/enhanced, e que type sharing automático é o diferencial da versão 2.

9. Mapa de revisão da trilha — as 26 notas

Para revisar antes de uma call: leia o TL;DR de cada nota, começando pelas notas com ⭐ da sua fase de deficiência.

Fase Iniciado — o porquê e as fundações

NotaO que cobrePeso entrevista
01 - Por que tooling e build existemO gap source↔runtime; o pipeline completo; por que tooling existe⭐⭐
02 - A evolução do tooling JS - de script ao bundler modernoA narrativa histórica: por que cada geração de ferramenta nasceu
03 - Package managers - npm, pnpm, yarn e Bunnode_modules, content-addressable store, phantom deps, workspaces⭐⭐
04 - Gerenciando versões de Nodenvm/fnm/Volta/mise, corepack, engines no package.json
05 - Semver e o grafo de dependênciassemver ranges, lockfiles, resolução de conflitos, peer deps
06 - ESM e CJS e o sistema de módulosA dualidade ESM/CJS, exports map, interop, por que ESM é necessário⭐⭐
07 - O grafo de módulos e o que é bundlingComo o bundler constrói o grafo; chunks; o que bundling realmente faz⭐⭐
08 - Transpilação e targetsBabel vs SWC vs esbuild vs tsc; browserslist; polyfills vs shims⭐⭐
09 - Dev server e HMRDev vs prod; ESM nativo no Vite; como HMR funciona⭐⭐

Fase Adepto — as ferramentas

NotaO que cobrePeso entrevista
10 - Ferramentas legadas - Grunt, Gulp, Bower, Browserify e RequireJSO que eram, por que morreram; contexto histórico
11 - webpack - o veteranoentry/output/loaders/plugins/resolver; Module Federation⭐⭐
12 - Create React App e a era dos scaffoldersCRA sunset 2025; o problema dos scaffolders opinativos
13 - Vite a fundoO padrão moderno; dois modos; plugins; Rolldown; Vite 8⭐⭐⭐
14 - Rollup, esbuild e RolldownBundlers de baixo nível; quando cada um; a diferença entre os três⭐⭐
15 - Turbopack, Rspack e a corrida Rust-GoBundlers nativos; por que Rust/Go; Rspack como bridge de migração
16 - Linting, formatting e git hooksESLint/Biome/oxlint; Prettier; Husky/lint-staged; a nova paisagem⭐⭐
17 - Otimização de bundleTree-shaking, code splitting, lazy loading, sideEffects, bundle analyzer⭐⭐⭐
18 - O runtime como ferramenta de DX—watch, —env-file, tsx, TS nativo no Node 23+, tsx vs ts-node
19 - Test runner nativo (node-test) e o cenário de testesnode:test, Vitest, Jest, Bun test; quando cada um
20 - Bun como runtime e toolkit all-in-oneO toolkit unificado; quando Bun ganha; compatibilidade Node

Fase Magus — escala, produção, futuro

NotaO que cobrePeso entrevista
21 - Monorepos - workspaces, Turborepo, Nx e changesetsWorkspaces; Turborepo task cache; Nx affected builds; changesets⭐⭐
22 - Single Executable Apps (SEA) e empacotamentoNode SEA; Bun —compile; casos de uso para CLIs distribuídas
23 - Build em produção, CI e determinismoBuilds determinísticos; lockfiles; cache no CI; reproducible builds⭐⭐
24 - Supply chain e segurança de dependênciasnpm audit; SBOM; provenance; CVEs em deps; pinning vs ranges
25 - IA no tooling e buildIA gerando config; codemod automatizado; análise de bundle por IA
26 — esta notaDecision tree; futuro do ecossistema; bloco de entrevista⭐⭐⭐

flowchart LR
    subgraph Iniciado["🟢 Iniciado (01–09)"]
        direction TB
        I1["01 O porquê ⭐⭐"]
        I2["06 ESM/CJS ⭐⭐"]
        I3["07 Grafo+bundling ⭐⭐"]
        I4["08 Transpilação ⭐⭐"]
        I5["09 Dev server+HMR ⭐⭐"]
    end

    subgraph Adepto["🟡 Adepto (10–20)"]
        direction TB
        A1["11 webpack ⭐⭐"]
        A2["13 Vite ⭐⭐⭐"]
        A3["14 Rollup/esbuild/Rolldown ⭐⭐"]
        A4["16 Lint/format ⭐⭐"]
        A5["17 Otimização ⭐⭐⭐"]
    end

    subgraph Magus["🔴 Magus (21–26)"]
        direction TB
        M1["21 Monorepos ⭐⭐"]
        M2["23 CI+determinismo ⭐⭐"]
        M3["26 Esta nota ⭐⭐⭐"]
    end

    Entrevista(["Entrevista\nSênior"])

    Iniciado --> Adepto --> Magus --> Entrevista

    I1 -.-> Entrevista
    I2 -.-> Entrevista
    A2 -.-> Entrevista
    A5 -.-> Entrevista
    M3 -.-> Entrevista

Roteiro de revisão rápida (30 min antes da call):

  1. 01 — o pipeline completo. A resposta para “explique o processo de build”.
  2. 06 — a distinção ESM/CJS. Aparece em toda pergunta de tree-shaking.
  3. 07 — o que bundling realmente faz.
  4. 09 — como o Vite funciona no dev.
  5. 13 — o padrão moderno, o porquê do Rolldown.
  6. 17 — tree-shaking, code splitting, lazy loading.
  7. 21 — quando monorepo e como.
  8. Esta nota — frases em inglês da seção 6 + vocabulário da seção 7.

10. Armadilhas de entrevista consolidadas

"Vite é mais rápido porque usa ESM"

O que acontece: resposta incompleta que parece correta. Por quê: ESM nativo explica a velocidade no dev server — o browser faz os imports, não há bundle. No build de produção, o Vite usa Rolldown e faz bundle sim — ESM nativo em produção seria ineficiente (muitas requisições HTTP). Saber os dois modos é o que distingue quem entende de quem repete. Como evitar: sempre distinguir dev server (ESM nativo) de build de produção (Rolldown/bundle).

"Usar sempre pnpm porque é mais rápido"

O que acontece: recomendação correta mas por motivo superficial. Por quê: a vantagem real do pnpm em monorepos não é velocidade — é o isolamento. pnpm impede phantom dependencies estruturalmente. npm flat permite que você use uma lib sem declarar ela, e o bug aparece meses depois numa máquina limpa. Como evitar: ao recomendar pnpm, mencionar isolamento de dependências como motivo principal.

"Tree-shaking remove código morto"

O que acontece: definição correta mas incompleta. Por quê: tree-shaking é análise estática do grafo de ESM exports/imports. Requer que a lib seja marcada com "sideEffects": false no package.json. E requer ESM — CommonJS é opaco para análise estática. Muitas libs que parecem tree-shakeable não são porque distribuem CJS. Como evitar: sempre mencionar os três requisitos: ESM, sideEffects false, e que o bundler precisa de análise estática.

"Não preciso saber webpack — uso Vite"

O que acontece: pode surgir em vagas que mencionam manutenção de legado ou Module Federation. Por quê: Vite é a escolha certa para projetos novos. Mas entender webpack — entry, loaders, plugins, Module Federation — ainda aparece em entrevistas de empresas com código legado. E Module Federation v2 tem casos de uso genuínos para micro-frontends que Vite ainda não cobre com a mesma maturidade. Como evitar: ter o “quando webpack faz sentido” preparado: MF em produção, legado, migração via Rspack.


11. Perguntas de system design — tooling em escala

System design de tooling aparece em entrevistas Staff e Principal. Diferente das perguntas de conceito (seção 5), aqui o entrevistador quer ver como você projeta um sistema inteiro, não responde uma questão pontual.

”Projete o pipeline de build de uma aplicação com 500 mil linhas de código TypeScript em monorepo.”

Como estruturar a resposta (5 minutos):

1. Clarificação (1 min)
   - Quantos pacotes no monorepo? Apps ou libs?
   - Alvos: browser, Node, ambos?
   - Time size e frequência de deploy?
   - Constraint de latência de CI?

2. Decisões de estrutura (2 min)
   - Package manager: pnpm (isolamento de phantom deps)
   - Task runner: Turborepo (cache incremental de tarefas, afetados por mudança)
   - Bundler: Vite 8 por app browser; tsdown para libs npm-bound
   - Lint/format: Biome (zero config, zero deps, um binário)

3. Estratégia de cache (1 min)
   - Turborepo remote cache (Vercel ou self-hosted)
   - Artifact caching no CI: só rebuilda o que mudou no grafo de deps
   - Content hashing nos assets de produção

4. Trade-offs explícitos (1 min)
   - Nx vs Turborepo: Nx tem plugin ecosystem mais rico e affected builds granulares;
     Turborepo tem curva menor e performance similar para <50 pacotes
   - Rolldown vs Rollup para libs: Rolldown é mais rápido;
     Rollup tem mais casos de edge documentados para dual ESM+CJS exótico

Frase EN de abertura: “Before choosing tools, I’d clarify the shape of the monorepo — number of packages, deploy cadence, and whether CI latency is a hard constraint. For a repo at this scale, the central architectural decision is task orchestration with remote caching, not which bundler to use."


"Como você garantiria determinismo de build em CI?”

Determinismo de build significa: mesma entrada → mesma saída, em qualquer máquina, em qualquer momento. Um build não determinístico é um bug esperando para aparecer em produção às 2h da manhã.

As quatro camadas de determinismo:

  1. Lockfile commitado e respeitadopackage-lock.json, pnpm-lock.yaml ou bun.lockb no repositório. CI roda pnpm install --frozen-lockfile, não pnpm install. Diferença: --frozen-lockfile falha se o lockfile está desatualizado em vez de atualizá-lo silenciosamente.

  2. Versão fixa de Node/runtime.nvmrc, .node-version ou engines no package.json, reforçado com volta ou mise no CI. Runtime diferente pode mudar output do node:crypto, comportamento do --experimental-vm-modules, etc.

  3. Sem timestamps e sem IDs randômicos nos assets — bundlers modernos usam content hashing por padrão; confirmar que plugins customizados não injetam Date.now() ou Math.random() em nomes de arquivo.

  4. Cache de CI parametrizado pela chave correta — a chave de cache do GitHub Actions / GitLab CI deve incluir o hash do lockfile, não só o branch. Se o lockfile muda, o cache invalida. Se não, você reusa um node_modules de uma versão anterior e a build parece passar, mas o runtime é diferente do declarado.

O teste do determinismo

Se você pode fazer git checkout <sha> em qualquer máquina e pnpm build produz byte-a-byte o mesmo output que a build original, você tem determinismo real. Se não, você tem builds que “geralmente funcionam”.

Referência: 23 - Build em produção, CI e determinismo.


”Como você migraria um projeto de webpack para Vite sem quebrar produção?”

A resposta sênior não é “trocar o webpack.config.js por vite.config.ts”. É um processo em etapas que minimiza risco:


flowchart TD
    A["Auditoria inicial\n(plugins, loaders, Module Federation?)"]
    A --> B{"Tem Module\nFederation?"}
    B -->|"Sim"| MF["Caminho MF2:\nRspack + @module-federation/enhanced\n(drop-in, não precisa reescrever)"]
    B -->|"Não"| C{"Tem loaders\nwebpack-specific?"}
    C -->|"Sim (SVG transforms,\nworkers manuais, etc.)"| Rspack["Rspack como\nbridge (step 1):\nmesma API webpack,\n5-10× mais rápido"]
    C -->|"Não / poucos"| Direct["Migração direta\npara Vite 8"]
    Rspack --> D["Migrar loaders para\nplugins Vite gradualmente\n(feature flag por módulo)"]
    Direct --> E["vite.config.ts mínimo\n+ resolver aliases\n+ variáveis de ambiente"]
    D --> E
    E --> F["Comparar bundle\nanalysis antes/depois\n(Rollup Visualizer)"]
    F --> G["Shadow deploy:\nbuild Vite em paralelo\n(sem servir)"]
    G --> H["A/B test:\n10% tráfego → Vite\nmonitorar error rate"]
    H --> I["Rollout completo\n+ remover webpack"]

Como funciona o A/B test de dois builds estáticos

Para uma SPA, o A/B test de bundler requer roteamento na borda — não existe nativamente. O mecanismo: dois deploys separados coexistem (ex.: /dist-webpack/ e /dist-vite/), e um proxy ou CDN rule decide qual index.html servir com base em um cookie ou percentual de tráfego. As opções mais comuns:

  • Cloudflare Workers: um Worker intercepta a requisição e redireciona baseado em cookie ou random hash — zero infraestrutura nova se você já usa Cloudflare.
  • CDN split testing: Vercel, Netlify e Cloudflare Pages têm split testing nativo via painel — dois branches, cada um com seu build.
  • Reverse proxy: nginx ou Caddy com split_clients por porcentagem de IP hash. O monitoramento é o ponto crítico: error rate no Sentry/DataDog por build_variant cookie. Se o Vite build tiver mais erros JS não capturados, você vê o delta antes de afetar 100% dos usuários.

O que frequentemente quebra na migração:

  • require() dinâmico — Vite ESM não suporta require() em runtime; precisa converter para import() dinâmico ou usar createRequire.
  • Aliases de path@/ funcionando em webpack com resolve.alias; em Vite precisa de resolve.alias equivalente e confirmar que o tsconfig.json paths bate.
  • Variáveis de ambiente — webpack usa process.env.X; Vite usa import.meta.env.X. Frequentemente há shim necessário.
  • Workersnew Worker(new URL('./worker.js', import.meta.url)) é ESM; webpack tinha sintaxe diferente.

Frase EN: “I’d start by auditing webpack-specific plugins and loaders. If there’s Module Federation, Rspack is the bridge — same API, Rust performance, and MF2 support. For direct migration, the critical items are dynamic require calls, environment variable syntax (process.env vs import.meta.env), and Worker instantiation patterns."


"Como você diagnosticaria um bundle de produção que cresceu 40% depois de uma sprint?”

Esta é uma pergunta de debugging de build, mas sêniors a abordam sistematicamente:

1. Quantificar: bundle analyzer (Rollup Visualizer, webpack-bundle-analyzer)
   → visualiza o grafo de chunks; identifica os maiores módulos

2. Hipóteses por categoria:
   (a) Dep nova ou actualizada com peso inesperado?
       → git diff package.json; verificar tamanho da nova dep no bundlephobia.com
   (b) Tree-shaking falhou?
       → checar se a lib tem "sideEffects: false" no package.json
       → checar se é CJS (não tree-shakeable) ou ESM
   (c) Importação barrel file?
       → import { Button } from 'ui-lib' que importa o pacote inteiro; usar import direto
   (d) Code splitting quebrado?
       → um chunk que deveria ser lazy-loaded entrou no bundle principal
       → verificar se import() dinâmico foi convertido acidentalmente para estático

3. Validar: buildar antes do commit que causou o crescimento
   → comparar chunk sizes; isolar o delta

4. Instrumentar para o futuro: bundlesize ou size-limit no CI
   → pull request falha se bundle passar de X KB

Frase EN: “My first step is always to open the bundle visualizer and look at the module graph. Growth almost always falls into four buckets: a new dependency that wasn’t tree-shaken, a barrel import that pulled in more than intended, a dynamic import that got inlined, or a code path that bypassed code splitting. I’d then instrument CI with size-limit to catch regressions automatically.”

Referência: 17 - Otimização de bundle.


12. Cenários avançados de entrevista

Cenário: “Você assumiu um projeto com 8 minutos de CI. O que você faz?”

Este é o tipo de pergunta open-ended que separa sênior de pleno. Resposta estruturada em camadas:

Camada 1 — Diagnóstico (antes de otimizar, medir):

  • Onde o tempo vai? time por etapa: install, typecheck, lint, test, build.
  • Quanto é paralelo e quanto é sequencial? Jobs paralelos no CI têm overhead de startup; etapas sequenciais são o gargalo real.

Camada 2 — Vitórias rápidas (sem mudança de arquitetura):

  • Cache do node_modules parametrizado pelo hash do lockfile.
  • Rodar lint, typecheck e test em paralelo (jobs separados).
  • Substituir Jest por Vitest ou Bun test — Vitest em projetos modernos é 3–10× mais rápido que Jest por usar esbuild para transpilação.
  • Substituir tsc para typecheck por tsc --noEmit sem build, ou usar ts-blank-space/oxc-transform para transpilação.

Camada 3 — Otimização estrutural:

  • Em monorepo: Turborepo remote cache — só rebuilda pacotes com mudança no grafo.
  • Afected-only tests: rodar apenas testes dos pacotes afetados pelo diff.
  • Build de produção: Rolldown/Vite 8 é 4–20× mais rápido que Rollup puro.

Camada 4 — Arquitetura (investimento maior):

  • Separar typecheck de build — são processos diferentes com objetivos diferentes.
  • Considerar distributed test execution (sharding nativo do Vitest, ou via TestOps).
  • Docker layer caching para builds que empacotam contêineres.

Frase EN: “Eight minutes tells me something is sequential that shouldn’t be — probably install, typecheck, lint, and tests running in order on one machine. I’d parallelize aggressively first, add lockfile-keyed cache for node_modules, and switch to Vitest if still on Jest. In a monorepo, Turborepo remote cache with affected-only runs is usually the biggest single improvement.”


Cenário: “O que você faria diferente se tivesse que fazer o projeto atual de zero, do ponto de vista de tooling?”

Esta é uma pergunta de reflexão estratégica. O entrevistador quer ver:

  1. Que você aprendeu com decisões passadas
  2. Que você conhece o ecossistema atual
  3. Que você articula trade-offs, não só moda

Estrutura de resposta (sem inventar projeto específico):

“If I were starting fresh with the current ecosystem, I’d lean on convention over configuration from the start. Vite 8 as the dev and build engine — the Rolldown unification means I don’t have to maintain separate dev and prod configurations. pnpm workspaces for dependency management with strict isolation from day one — phantom dependencies are much harder to eliminate than to prevent. Biome for lint and format — one binary, zero config, zero CI dependency on Node version for tooling. And I’d set up size-limit in CI from the first PR, not after the bundle becomes a problem.”

“The thing I’d do differently is not treat tooling as a one-time setup. Config files rot. Deps drift. The teams that win are the ones that have a quarterly tooling hygiene check — update deps, run the audit, re-evaluate whether the tool still fits the use case.”


tsdown — o bundler elegante para bibliotecas

14 - Rollup, esbuild e Rolldown introduz os motores. tsdown é a camada de DX acima deles, otimizada para autores de biblioteca.

AspectotsdownRollup 4esbuild
Baseado emRolldown (Rust)Rollup (JS)Go
Velocidade~Rolldown (muito rápido)Mais lentoMuito rápido
DTS geraçãoNativa via isolatedDeclarationsPlugin rollup-plugin-dtsNão nativo
Dual ESM+CJSAutomáticoManual com configManual
Parte do ecossistemaVoidZero / Vite+StandaloneStandalone
Config mínimaZero (auto-detect entry)MédiaAlta para libs

tsdown é o que vite lib mode usará internamente a partir do Vite 8+, e faz parte do toolchain vp (Vite+). Para libs novas com TypeScript, é a escolha com menor custo de manutenção em 2026.

Fonte: tsdown.dev — documentação oficial.


Module Federation 2.0 — o mapa real em 2026

A nota da árvore de decisão (seção 2) menciona Module Federation; aqui o detalhe que aparece em perguntas avançadas.

O que MF 2.0 adicionou (estável desde abril/2026):

RecursoMF 1.x (webpack)MF 2.0 (@module-federation/enhanced)
Suporte a bundlerswebpack onlywebpack, Rspack, Vite, Rollup
TypeScript typesManual (sem sharing)Type sharing automático entre remotes
Host discoveryEstático (URL hardcoded)Manifest-based (dynamic runtime discovery)
Runtimewebpack runtimeRuntime unificado cross-bundler
MaturidadeProdução (anos)Estável desde abr/2026

Quando a resposta é ainda webpack + MF1: Equipes com MF1 em produção por anos, com comportamento documentado e testado. Migrar para MF2 é válido, mas o risco de regressão em produção às vezes não justifica. Rspack + MF2 é o caminho de menor risco: drop-in API, build muito mais rápido.

Quando é MF2 novo projeto: Sempre. MF2 é tecnicamente superior em todos os aspectos e funciona cross-bundler.

Fonte: InfoQ — Module Federation 2.0 Reaches Stable Release.


O que vem a seguir

Tooling e Build como disciplina para aqui. O próximo horizonte natural é a aplicação do tooling dentro de frameworks:

  • React — como Vite, Next.js, Turbopack e bundlers se encaixam no ciclo de vida React; RSC e o modelo de bundling do React 19.
  • Node — Node como runtime de produção (não de DX); SEA, performance do runtime, deploy.
  • capstone de TypeScript — a trilha irmã; TypeScript e tooling são inseparáveis na prática; o capstone de TS tem o mesmo formato que esta nota.

Veja também

Notas da trilha (confirmadas via ls)

Fundações (Iniciado):

Ferramentas (Adepto):

Escala e Produção (Magus):

Trilha irmã:


Referências

Lastro

Esta nota é o CAPSTONE da trilha Tooling e Build (nota 26/26). As seções técnicas sintetizam as notas 01–25, que carregam o lastro técnico de cada afirmação. Os parágrafos em inglês da seção 6 são postura técnica genérica — NÃO são relatos de projetos, clientes ou experiências específicas do autor. Os dados sobre Vite 8, Rolldown, Biome, oxlint e VoidZero são baseados em fontes primárias (anúncios oficiais) de 2025–2026 listadas na seção Fontes.


Tooling em uma frase: o pipeline de build existe para fechar o gap entre o que você escreve e o que roda — e entender cada etapa desse pipeline é o que separa quem configura ferramentas de quem as entende.