Monorepo conceitos, dicas e truques orientados ao redor do NextJs
Howtos para Monorepo. Novo para Monorepos? Verifique esta FAQ. Este exemplo é gerenciado pelo turborepo e no YARN 4 com a abordagem de aliases de caminho de digitalização. Não é a única maneira de fazer.
Útil para
Se você estiver gostando de alguns dos meus trabalhos de OSS em sua empresa, eu realmente apreciaria um patrocínio, um café ou uma estrela caída. Isso me dá mais tempo para melhorá -lo para o próximo nível.
| Jetbrains | Embie.be | Vercel |
corepack enable
yarn install .
├── apps
│ ├── nextjs-app (i18n, ssr, api, vitest)
│ └── vite-app
└── packages
├── common-i18n (locales...)
├── core-lib
├── db-main-prisma
├── eslint-config-bases (to shared eslint configs)
└── ui-lib (emotion, storybook)
Os aplicativos não devem depender de aplicativos, eles podem depender de pacotes
Os aplicativos podem depender de pacotes, os pacotes podem depender um do outro ...
.
├── apps
│ ├── vite-app (Vite app as an example)
│ │ ├── src/
│ │ ├── package.json (define package workspace:package deps)
│ │ └── tsconfig.json (define path to packages)
│ │
│ └── nextjs-app (NextJS app with api-routes)
│ ├── e2e/ (E2E tests with playwright)
│ ├── public/
│ ├── src/
│ │ └── pages/api (api routes)
│ ├── CHANGELOG.md
│ ├── next.config.mjs
│ ├── package.json (define package workspace:package deps)
│ ├── tsconfig.json (define path to packages)
│ └── vitest.config.ts
│
├── packages
│ ├── core-lib (basic ts libs)
│ │ ├── src/
│ │ ├── CHANGELOG.md
│ │ ├── package.json
│ │ └── tsconfig.json
│ │
│ ├── db-main-prisma (basic db layer with prisma)
│ │ ├── e2e/ (E2E tests)
│ │ ├── prisma/
│ │ ├── src/
│ │ ├── CHANGELOG.md
│ │ ├── package.json
│ │ └── tsconfig.json
│ │
│ ├── eslint-config-bases
│ │ ├── src/
│ │ ├── CHANGELOG.md
│ │ ├── package.json
│ │ └── tsconfig.json
│ │
│ └── ui-lib (basic design-system in react)
│ ├── src/
│ ├── CHANGELOG.md
│ ├── package.json
│ └── tsconfig.json
│
├── static (no code: images, json, locales,...)
│ ├── assets
│ └── locales
├── docker (docker...)
│ ├── .dockerignore
│ ├── docker-compose.yml (compose specific for nextjs-app)
│ ├── docker-compose.db.yml (general services like postgresql...)
│ └── Dockerfile (multistage build for nextjs-app)
├── .yarnrc.yml
├── package.json (the workspace config)
└── tsconfig.base.json (base typescript config)
{
"name" : "nextjs-monorepo-example" ,
// Set the directories where your apps, packages will be placed
"workspaces" : [ "apps/*" , "packages/*" ] ,
//...
} O gerente de pacotes irá digitalizar esses diretórios e procurar o Children package.json . Seu conteúdo é usado para definir a topologia da área de trabalho (aplicativos, libs, dependências ...).
Crie uma pasta em ./packages/ diretório com o nome do seu pacote.
mkdir packages/magnificent-poney
mkdir packages/magnificent-poney/src
cd packages/magnificent-poneyInicialize um package.json com o nome do seu pacote.
Em vez de digitar
yarn init, prefira tomar o ./packages/ui-lib/package.json como um exemplo de funcionamento e editar seus valores.
{
"name" : "@your-org/magnificent-poney" ,
"version" : "0.0.0" ,
"private" : true ,
"scripts" : {
"clean" : "rimraf ./tsconfig.tsbuildinfo" ,
"lint" : "eslint . --ext .ts,.tsx,.js,.jsx" ,
"typecheck" : "tsc --project ./tsconfig.json --noEmit" ,
"test" : "run-s 'test:*'" ,
"test:unit" : "echo "No tests yet"" ,
"fix:staged-files" : "lint-staged --allow-empty" ,
"fix:all-files" : "eslint . --ext .ts,.tsx,.js,.jsx --fix" ,
} ,
"devDependencies" : {
"@your-org/eslint-config-bases" : "workspace:^" ,
} ,
}Primeiro, adicione o pacote ao App Package.json. A maneira recomendada é usar o protocolo da área de trabalho suportada pelo YARN e PNPM.
cd apps/my-app
yarn add @your-org/magnificent-poney@ ' workspace:^ 'A inspiração pode ser encontrada em aplicativos/nextJs-App/package.json.
{
"name" : "my-app" ,
"dependencies" : {
"@your-org/magnificient-poney" : "workspace:^" ,
} ,
} Em seguida, adicione um alias de caminho digital no app tsconfig.json. Isso permitirá que você importá -lo diretamente (sem necessidade de compilação)
A inspiração pode ser encontrada em Apps/NextJS-App/Tsconfig.json.
{
"compilerOptions" : {
"baseUrl" : "./src" ,
"paths" : {
// regular app aliases
"@/components/*" : [ "./components/*" ] ,
// packages aliases, relative to app_directory/baseUrl
"@your-org/magnificent-poney/*" : [
"../../../packages/magnificent-poney/src/*" ,
] ,
"@your-org/magnificent-poney" : [
"../../../packages/magnificent-poney/src/index" ,
] ,
} ,
} ,
}PS:
- Não tente definir aliases no global tsonfig.base.json para se manter rigoroso com dependências gráficas.
- A estrela em
@your-org/magnificent-poney/*permite importar subpastas. Se você usar um arquivo de barril (index.ts), o alias com estrela poderá ser removido.
Edite seu next.config.mjs e ative a opção Experimental.externaldir. Feedbacks aqui.
const nextConfig = {
experimental : {
externalDir : true ,
} ,
} ;Se você estiver usando uma versão mais antiga do NextJS e não tiver o sinalizador experimental, basta substituir sua configuração do WebPack.
const nextConfig = {
webpack : ( config , { defaultLoaders } ) => {
// Will allow transpilation of shared packages through tsonfig paths
// @link https://github.com/vercel/next.js/pull/13542
const resolvedBaseUrl = path . resolve ( config . context , "../../" ) ;
config . module . rules = [
... config . module . rules ,
{
test : / .(tsx|ts|js|jsx|json)$ / ,
include : [ resolvedBaseUrl ] ,
use : defaultLoaders . babel ,
exclude : ( excludePath ) => {
return / node_modules / . test ( excludePath ) ;
} ,
} ,
] ;
return config ;
} ,
} ;PS: Se o seu pacote compartilhado fizer uso do SCSS Bundler ... uma configuração WebPack personalizada será necessária ou usará os módulos de transpilação seguintes, consulte as Perguntas frequentes abaixo.
Os pacotes agora estão vinculados ao seu aplicativo, basta importá-los como pacotes regulares: import { poney } from '@your-org/magnificent-poney' .
Opcional
Se você precisar compartilhar alguns pacotes fora do Monorepo, poderá publicá -los em NPM ou repositórios privados. Um exemplo baseado no microbundle está presente em cada pacote. Versão e publicação podem ser feitas com Atlassian/mudanças, e é simples como digitar:
$ yarn g:changesetSiga as instruções ... e comprometa o arquivo de alterações. Um P/R de "Pacotes de versão" aparecerá após as verificações do CI. Ao mesclá -lo, uma ação do GitHub publicará os pacotes com a versão semver resultante e gerará Changelogs para você.
PS:
- Mesmo se você não precisar publicar, o ChangeSet pode manter um Changelog automático para seus aplicativos. Legal !
- Para desativar a publicação automática de alguns pacotes, basta definir
"private": "true"em seu package.json.- Deseja ajustar o comportamento, consulte .Changeset/config.json.
Alguns scripts de conveniência podem ser executados em qualquer pasta deste repositório e chamarão seus colegas definidos em pacotes e aplicativos.
| Nome | Descrição |
|---|---|
yarn g:changeset | Adicione uma troca para declarar uma nova versão |
yarn g:codegen | Execute o CodeGen em todos os espaços de trabalho |
yarn g:typecheck | Execute o TypeChecks em todos os espaços de trabalho |
yarn g:lint | Exibir problemas de Linnter em todos os espaços de trabalho |
yarn g:lint --fix | Tente executar o Linter Auto-Fix em todos os espaços de trabalho |
yarn g:lint-styles | Exibir problemas de Stylelint CSS em todos os espaços de trabalho |
yarn g:lint-styles --fix | Tente executar problemas de fixação automática do Stylelint em todos os espaços de trabalho |
yarn g:test | Executar testes de unidade e E2E em todos os espaços de trabalho |
yarn g:test-unit | Executar testes de unidade em todos os espaços de trabalho |
yarn g:test-e2e | Execute testes E2E em todos os espaços de trabalho |
yarn g:build | Executar construir em todos os espaços de trabalho |
yarn g:clean | Clean Builds em todos os espaços de trabalho |
yarn g:check-dist | Certifique -se de que os arquivos distiços da construção passam ES2017 (execute g:build primeiro). |
yarn g:check-size | Verifique se os arquivos distintos do navegador estão dentro do limite de tamanho (execute g:build primeiro). |
yarn clean:global-cache | Caches de ferramentas limpas (Eslint, brincadeiras ...) |
yarn deps:check --dep dev | Imprimirá quais pacotes podem ser atualizados globalmente (veja também .ncurc.yml) |
yarn deps:update --dep dev | Aplique atualizações possíveis (execute yarn install && yarn dedupe After) |
yarn install:playwright | Instale dramaturgo para E2E |
yarn dedupe | Deduplicação de fios embutidos do arquivo de bloqueio |
Por que usar
:para prefixar nomes de scripts? É conveniente no Yarn 3+, podemos chamar esses scripts de qualquer pasta no Monorepo.g:é um atalho paraglobal:. Consulte a lista completa no root package.json.
O Global Commands yarn deps:check and yarn deps:update ajudará a manter as mesmas versões em todo o Monorepo. Eles são baseados nos excelentes npm-updates (consulte Opções, ou seja: yarn check:deps -t minor ).
Após a execução
yarn deps:update, é necessária umayarn install. Para evitar ter duplicatasyarn dedupeyarn dedupe --check. A verificação duplicada é aplicada no exemplo do GitHub Ações.
Consulte um exemplo em ./apps/nextjs-app/.eslinTrc.js e nossas bases esconfig.
Verifique o conteúdo da pasta .husky para ver quais ganchos estão ativados. É usado com fiapos para garantir que os fiapos e os mais bonitos sejam aplicados automaticamente em comprometimento e/ou empurrões.
Os testes dependem de TS-jest ou Vitest, dependendo do aplicativo. Todas as configurações suportam aliases do caminho do título. A biblioteca de teste de reação é ativada sempre que o React está envolvido.
A configuração vive na pasta raiz de cada aplicativo/pacotes. Como exemplo, veja
Você encontrará alguns exemplos de fluxos de trabalho para a ação do GitHub nos fluxos de trabalho .github. Por padrão, eles garantirão que
Cada uma dessas etapas pode ser optada.
Para garantir um desempenho decente, esses recursos estão presentes nas ações de exemplo:
Cache de pacotes (Node_modules ...) - Instale em torno de 25s
Cache do NextJS Build anterior - construído em torno de 20 anos
Acionado quando alterado usando os caminhos de ações, ou seja:
paths: - "apps/nextjs-app/**" - "packages/**" - "package.json" - "tsconfig.base.json" - "yarn.lock" - ".yarnrc.yml" - ".github/workflows/**" - ".eslintrc.base.json" - ".eslintignore"
O plug -in ESLint exige que a configuração eslint.workingDirectories esteja definida:
"eslint.workingDirectories": [
{
"pattern": "./apps/*/"
},
{
"pattern": "./packages/*/"
}
],
Mais informações aqui
VERCEL Suporte de monorepos nativamente, consulte o documento vercel-monorepo-de-implantado.
Há um exemplo básico para criar uma imagem do Docker, leia o documento do documento.
As receitas Netlify, AWS-amplify, K8S-Docker, sem servidor sem servidor podem ser adicionadas no futuro. PR são bem -vindos também.
As dependências e dependências de devDependos de aplicativos são fixados em versões exatas. Os Pacotes Deps usarão os Semver compatíveis. Para obter mais informações sobre essa alteração, consulte o raciocínio aqui e nosso arquivo de configuração renovabot.json5.
Para ajudar a manter os DEPS atualizados, consulte o yarn deps:check && yarn deps:update scripts e / ou use o RenovateBot.
Ao adicionar um DEP através da CLI do fio (ou seja: YARN Adicione alguma coisa), é possível definir o comportamento de exceção salvar automaticamente, definindo
defaultSemverRangePrefix: ""em yarnrc.yml. Mas isso tornaria o padrão para pacotes/* também. Melhor para lidar comyarn add something --exactpor caso.