Quando você começa a pensar em monorepos TypeScript, suas opções se expandem rapidamente. pnpm, bun, Turborepo, Nx, Changesets, Biome. Todas parecem corretas, mas se você colocar todas desde o início, vai ficar pesado. Por outro lado, se você cortar tudo, terá problemas mais tarde.
A razão pela qual este tipo de discussão é difícil de organizar é que apenas procuramos a “solução óptima” sem considerar as premissas. É melhor separar a solução de uso geral e fácil de entender e a solução prática para a configuração que está à sua frente.
Desta vez, organizarei as duas partes a seguir.
- Configuração segura ao criar um novo monorepo TypeScript
- Configuração realista baseada nas suposições específicas de
apps/web,apps/wxt,packages/ui,packages/core
Primeiro, a conclusão
| Pré-requisitos | Primeira configuração a escolher | Suplemento |
|---|---|---|
| Novo monorepo genérico. No futuro, o lançamento de pacotes, a otimização de CI e a integração do Docker serão considerados | pnpm workspace + Turborepo + TypeScript Project References + package.json de exports + Changesets | O mais estável |
Configuração de 4 pacotes: apps/web, apps/wxt, packages/ui, packages/core. Eu não uso Docker. Não publique pacotes compartilhados no npm | pnpm workspace + Biome + TypeScript Project References | Turborepo não é necessário nesta fase |
| Bun fornece o ambiente de execução, gerenciador de pacotes e teste | bun workspace também é candidato | No entanto, pnpm é forte em termos de operação segura |
Resumindo, pnpm + turbo é forte na teoria geral. Porém, neste caso, workspace only é suficiente.
Uso geral não difícil
A partir de 2026, se você quiser começar sem se preocupar profundamente, pnpm workspace é a base mais estável. workspace é fornecido como padrão, referências de pacotes locais podem ser explicitadas com o protocolo workspace: e os pacotes de destino podem ser reduzidos consideravelmente com --filter.
Use Referências de projeto TypeScript para limites de tipo. A documentação oficial do TypeScript também afirma claramente que projetos divididos podem melhorar o tempo de construção, a separação lógica e a construção em ordem de dependência usando tsc --build. Isso é bastante eficaz no monorepo.
Se você adicionar Turborepo além disso, você terá gráfico de tarefas, cache, execução paralela e turbo prune de uma só vez. [Configurações de tarefas do Turborepo] (https://turborepo.dev/docs/crafting-your-repository/configuring-tasks) só precisam ser montadas em torno de dependsOn e outputs, e há espaço para crescimento à medida que o repo cresce.
Se você tiver um pacote para publicar, Changesets também se encaixará naturalmente. documentação do espaço de trabalho do pnpm também assume que uma ferramenta dedicada como Changesets é usada para versionamento de pacotes em um espaço de trabalho.
Em outras palavras, a solução não difícil de uso geral é a seguinte.
| Função | Recomendação |
|---|---|
| gestão de espaços de trabalho | pnpm workspace |
| Limites de tipo e construções incrementais | TypeScript Project References |
| Execução de tarefas, paralelização e armazenamento em cache | Turborepo |
| face pública do limite do pacote | exports de package.json |
| versionamento / changelog | Changesets |
| fiapos/formato | Biome ou ESLint + Prettier. É mais fácil começar com Biome agora |
Por que Turborepo ainda não é necessário nesta premissa?
A configuração desta vez é bastante simples.
packages/corepackages/ui -> packages/coreapps/web -> packages/ui, packages/coreapps/wxt -> packages/ui, packages/coreSe as dependências estiverem neste nível, executar o filtro em pnpm workspace e tsc -b é suficiente para operação.
Por exemplo, o valor da inclusão de Turborepo aumenta repentinamente em situações como esta.
| Dor | Por que Turborepo funciona |
|---|---|
| O tempo total de construção/teste/lint é longo | O cache e a execução paralela são eficazes |
| Quero esclarecer a ordem de dependência das tarefas | dependsOn pode expressar um gráfico |
| Quero acelerar o CI | Cache remoto funciona |
| Quero extrair apenas os pacotes necessários para Docker | turbo prune pode ser usado |
Por outro lado, se você instalá-lo em um estágio em que ainda não está com tantos problemas, é difícil ver o valor além de adicionar mais um arquivo de configuração. Se você desligar o Docker, o apelo de prune cairá um pouco. Changesets também não é necessário se você não publicar pacotes compartilhados no npm.
Portanto, com base nesta premissa, é razoável começar com pnpm workspace + Biome + TypeScript Project References.
Como cortar camadas
Nesta divisão em quatro partes, é mais importante evitar ambiguidade nas funções do que na seleção de ferramentas.
| Caminho | Coisas para colocar | Coisas que você não deveria colocar |
|---|---|---|
packages/core | domínio, esquema, validação, cliente API, função pura, modelo de estado | UI, roteamento, API do navegador |
packages/ui | Componente/gancho React independente do ambiente | Processamento específico WXT, roteador, armazenamento de extensão |
apps/web | Montagem como aplicação web, página, roteamento, adaptador | circunstâncias específicas de extensão |
apps/wxt | script de plano de fundo/conteúdo, API do navegador, configurações específicas do WXT | Roteamento específico da Web, lógica pura que pode ser colocada na camada compartilhada |
A última coisa que quero evitar é transformar packages/ui em um lugar para todas as coisas compartilhadas. Quando circunstâncias específicas e roteamento de browser extension começam a entrar aqui, ele se torna um ponto de conexão em vez de uma camada compartilhada. Se isso acontecer, os benefícios do monorepo diminuirão.
Notas sobre apps/wxt
Você deve ter um pouco de cuidado com apps/wxt. Configurações WXT TypeScript geralmente estende .wxt/tsconfig.json do tsconfig.json do root. No entanto, monorepo pode não assumir esse formato; nesse caso, você precisa incluir .wxt/wxt.d.ts em seu projeto TypeScript.
Em outras palavras, embora apps/wxt faça parte do monorepo, é mais estável tratá-lo como um projeto TypeScript independente.
Não use tsconfig.paths como principal meio de referências internacionais
Isto é muito importante.
Notas de versão do TypeScript 5.7 afirma claramente que as importações que dependem de baseUrl e paths não podem ser reescritas ao gerar JS. Em outras palavras, um design que ultrapassa os limites do pacote usando apenas tsconfig.paths pode passar na verificação de tipo, mas provavelmente será distorcido na fase de execução ou publicação.
Basicamente, você deve considerar as referências transfronteiriças no monorepo na seguinte ordem.
- Pacotes separados
- Conecte dependências com
workspace: - Decida o lado público com
exportsdepackage.json - Crie uma construção de pedido de dependência com
TypeScript Project References
paths tem menos probabilidade de ser danificado se for mantido como auxiliar dentro da embalagem.
Biome se encaixa bem nesta premissa
Acho que a decisão de remover ESLint e focar em Biome é bastante natural. Guia de grandes projetos do Biome também organiza a premissa de usar a configuração raiz e a configuração aninhada de maneira diferente para grandes repositórios, como monorepo e espaço de trabalho. Na v2, também é introduzida uma configuração baseada em monorepo.
Nessa escala, seria mais simples enviar o lint/formato para Biome e cuidar apenas do limite do projeto e construir no lado TypeScript.
Imagem de configuração mínima
Isso é suficiente para a configuração inicial.
- Coloque
pnpm-workspace.yamlna raiz - Coloque o estilo de solução
tsconfig.jsonna raiz ereferencescada pacote packages/coreepackages/uihabilitamcomposite- Pacote compartilhado especifica
exportsdepackage.json - Coloque
biome.jsonna raiz - Para
apps/wxt, verifique separadamente como lidar com definições de tipo WXT.
Neste ponto, você pode lutar por bastante tempo.
Quando adicionar a próxima ferramenta
| O que adicionar | Quando adicionar |
|---|---|
Turborepo | Build/test/lint é pesado, otimização de CI é necessária, quero esclarecer o gráfico de tarefas |
Changesets | Quero gerenciar versões e publicar um pacote compartilhado |
Nx | Eu queria geração automática, poliglota e gerenciamento monorepo mais forte |
Migrando para bun workspace | Eu queria unificar o tempo de execução/gerenciador de pacotes/teste para Bun |
Com o monorepo, funciona melhor adicionar apenas onde ocorre a dor, em vez de adicionar tudo desde o início.
resumo
Não existe uma solução ideal para o monorepo TypeScript. pnpm workspace + Turborepo + TypeScript Project References é forte para respostas não difíceis de uso geral. No entanto, se o Docker e a publicação de pacotes ainda não forem muito pesados após a divisão em apps/web, apps/wxt, packages/ui e packages/core, seria mais leve e menos provável de quebrar se você começar com pnpm workspace + Biome + TypeScript Project References.
O importante não é aumentar o número de ferramentas, mas manter core e ui escassos e expressar referências transfronteiriças honestamente com workspace: e exports. Se isso não falhar, não será tarde demais para adicionar turbo mais tarde.
hsb.horse