ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

使用 Turborepo 搭建 NestJS + Next.js 全栈 Monorepo:with-nestjs 示例深度解析

2026/9/19 20:05:04 拓冰建站 浏览量
使用 Turborepo 搭建 NestJS + Next.js 全栈 Monorepo:with-nestjs 示例深度解析 构建工具开发工具CLI【免费下载链接】turboBuild system optimized for JavaScript and TypeScript, written in Rust项目地址https://gitcode.com/gh_mirrors/tu/turbo点击查看免费下载本指南以 Turborepo 官方示例examples/with-nestjs为主线完整拆解如何用 Turborepo 将一个 NestJS 后端 API、一个 Next.js 前端 Web 应用以及共享的 ESLint / Jest / TypeScript / UI 包编排进同一个 pnpm workspace并覆盖构建、开发、测试、类型检查、格式化与远程缓存Remote Caching的完整工作流。读完本文你将能够复现这套 monorepo 结构理解turbo.json任务编排的底层语义并掌握共享 NestJS 资源包repo/api的模块化实践。examples/with-nestjs是 Turborepo 官方维护的社区示例community-maintained example它借鉴了with-nextjs示例的 monorepo 骨架与 NestJS 官方01-cats-app示例的资源组织方式是“Node 全栈 类型安全 共享配置”类 monorepo 的典型范本。一、快速上手创建项目与其它 Turborepo 示例一致with-nestjs可以通过create-turbo一键拉取npx create-turbolatest -e with-nestjs命令执行后会在当前目录生成一个完整的 pnpm workspace其中已经预置了 NestJS 与 Next.js 两套应用、五个共享包以及开箱即用的 lint / test / build 配置。由于示例使用 pnpm 作为包管理器进入目录后建议先确认环境满足根目录 package.json 声明的约束packageManager: pnpm12.4.1且engines.node 24.11.0。然后执行pnpm install即可安装全部依赖并开始开发。二、仓库结构apps 与 packages 如何划分with-nestjs的完整目录结构如下. ├── apps │ ├── api # NestJS app │ └── web # Next.js app └── packages ├── repo/api # Shared NestJS resources ├── repo/eslint-config # ESLint configurations含 Prettier ├── repo/jest-config # Jest configurations ├── repo/typescript-config # 全仓库共用的 tsconfig.json └── repo/ui # 可复用的 React 组件库这种划分遵循了 Turborepo 的经典约定apps 放可独立部署的应用packages 放可被多个应用共享的库与配置。每个应用和包“mostly written in TypeScript”共享类型定义与编译配置。workspace 的装配点在根目录 pnpm-workspace.yamlpackages: - apps/* - packages/*这意味着apps/api、apps/web以及packages下的所有包都会被 pnpm 识别为 workspace 成员包与包之间通过workspace:*协议互相引用例如apps/api依赖repo/api: workspace:*见 apps/api/package.json。2.1 应用层NestJS API 与 Next.js Webapps/apiNestJS 后端监听3000端口。其dev脚本使用 SWC 编译加node --watch热重启而非默认的 webpack 构建链详见下文第五节。apps/webNext.js 前端dev脚本为next dev --turbopack --port 3001见 apps/web/package.json使用 Turbopack 作为开发打包器端口特意错开为3001避免与 API 的3000冲突。2.2 共享包repo/api的模块化价值repo/api是本示例最具 NestJS 特色的共享包它把 NestJS 应用中会被多个模块甚至未来会被 web 端引用的类型与 DTO抽离出来作为类型契约的单一来源。从 packages/api/src/entry.ts 可以看到它的导出面export { Link } from ./links/entities/link.entity; export { CreateLinkDto } from ./links/dto/create-link.dto; export { UpdateLinkDto } from ./links/dto/update-link.dto;apps/api中的LinksControllerapps/api/src/links/links.controller.ts正是通过import type { CreateLinkDto, UpdateLinkDto } from repo/api引用这些共享类型而LinksServiceapps/api/src/links/links.service.ts则直接消费Link实体。这套“实体/DTO 下沉到共享包、应用层只写控制器与服务”的写法让前后端乃至未来的移动端在请求体与响应体上天然保持类型一致。apps/api中的links模块提供了标准的 REST 资源示例Controller(links)下挂载了POST /links、GET /links、GET /links/:id、PATCH /links/:id、DELETE /links/:id五个端点并由LinksService基于内存数组实现 CRUD 骨架业务逻辑以TODO占位便于用户在此基础上继续扩展。三、命令体系一条命令跑遍全仓库根目录 package.json 用turbo run把任务分发到所有声明了对应scripts的应用与包上# Build all apps and packages that have a build script. pnpm build # Run development servers for all apps and packages that have a dev script. pnpm dev # Run unit tests for all apps and packages that have a test script. pnpm test # Run end-to-end tests for all apps and packages that have a test:e2e script. pnpm test:e2e # Lint all apps and packages that have a lint script. pnpm lint # Type-check all apps and packages that have a check-types script. pnpm check-types # Format supported TypeScript, TSX, and Markdown files. pnpm format各命令的行为由根目录 turbo.json 定义的任务描述符task descriptors决定{ $schema: https://turborepo.dev/schema.json, globalDependencies: [**/.env.*local], tasks: { build: { dependsOn: [^build], outputs: [.next/**, !.next/cache/**, !.next/dev/**, dist/**] }, check-types: { dependsOn: [^build] }, dev: { cache: false, persistent: true }, lint: {}, test: { dependsOn: [^build] }, test:e2e: { dependsOn: [^build] } } }几个关键语义值得展开dependsOn: [^build]^前缀表示“依赖上游包先完成 build”。例如apps/api依赖repo/api那么 Turborepo 会保证repo/api的build先跑完再执行apps/api的build、test、check-types。这正是 Turborepo 任务图task graph自动推导依赖关系的核心机制。outputs与缓存build声明了产物路径.next/**与dist/**并排除.next/cache、.next/devTurborepo 会基于这些产物做缓存命中判定命中时直接还原上一次的输出跳过重跑。dev任务cache: false表示开发服务器永远不缓存、不命中缓存persistent: true表示该任务是长驻进程Turborepo 不会等待它退出适合dev这类 watch 型任务。globalDependencies: [**/.env.*local]本地环境变量文件被声明为全局依赖一旦内容变化会触发相关任务缓存失效——避免把带密钥的.env.local结果错误地复用到其它环境。需要说明的是任务描述符只对“在该包中实际存在对应 script”的任务生效例如test:e2e只有apps/api定义了jest --config ./test/jest-e2e.json见 apps/api/package.json因此pnpm test:e2e只会作用于该应用。四、共享配置包ESLint / Jest / TypeScript 的复用之道with-nestjs将跨应用的工程化配置全部收敛到packages下避免每个应用各写一份4.1repo/typescript-configpackages/typescript-config/nestjs.json 是专门为 NestJS 定制的 tsconfig{ extends: ./base.json, compilerOptions: { allowSyntheticDefaultImports: true, emitDecoratorMetadata: true, experimentalDecorators: true, forceConsistentCasingInFileNames: false, incremental: true, noFallthroughCasesInSwitch: false, noImplicitAny: false, removeComments: true, sourceMap: true, strictNullChecks: false, strictBindCallApply: false } }其中experimentalDecorators与emitDecoratorMetadata是 NestJS 依赖注入与装饰器元数据的编译前提incremental开启增量编译以加速迭代。除nestjs.json外该包还提供base.json、nextjs.json、react-library.json供不同技术栈的应用按需extends。4.2repo/jest-configpackages/jest-config/src/nest.ts 展示了 NestJS 单元测试的基准配置const swcOptions { jsc: { parser: { syntax: typescript, decorators: true }, transform: { legacyDecorator: true, decoratorMetadata: true }, }, module: { type: commonjs }, } as const; export const nestConfig { ...baseConfig, rootDir: src, testRegex: .*\\.spec\\.ts$, transform: { ^.\\.(t|j)s$: [swc/jest, swcOptions], }, transformIgnorePatterns: [], collectCoverageFrom: [**/*.(t|j)s], coverageDirectory: ../coverage, testEnvironment: node, } as const satisfies Config;要点使用SWC 作为 Jest 的 transform并显式开启decorators/legacyDecorator/decoratorMetadata保证 NestJS 装饰器在测试环境中正常工作testRegex: .*\\.spec\\.ts$只匹配*.spec.ts单元测试文件transformIgnorePatterns: []表示不忽略任何 node_modules 依赖的转换这在 monorepo 中通常需要因为 workspace 内的源码包没有预编译产物testEnvironment: node符合后端服务的运行环境。apps/api的jest.config.ts即引用此配置apps/api/src/links/links.controller.spec.ts、links.service.spec.ts与apps/api/test/app.e2e-spec.ts基于supertest的端到端测试都是可直接运行的真实用例。4.3repo/eslint-configpackages/eslint-config提供base.js、library.js、nest.js、next.js、react-internal.js等预设nest.js专门承载 NestJS 的 lint 规则并内置prettier-base.js——这正是根目录pnpm format命令prettier --write **/*.{ts,tsx,md}格式化行为可定制化的依据想调整格式化规则改repo/eslint-config/prettier-base即可。4.4repo/uipackages/ui是 React 组件库button.tsx、card.tsx、code.tsx由apps/web通过repo/ui: workspace:*引用演示了“应用消费共享 UI 包”的典型链路。五、NestJS 应用的开发链路SWC watchwith-nestjs的apps/api没有使用 NestJS CLI 默认的 webpack 构建而是改用更轻量的 SWC 链路见 apps/api/package.jsondev: pnpm build concurrently -k \swc src -d dist --strip-leading-paths --watch\ \node --watch dist/main.js\, build: swc src -d dist --strip-leading-paths, start: node dist/main流程是先执行一次swc src -d dist把 TypeScript 编译到dist随后用concurrently并行启动“SWC watch 增量编译”与node --watch dist/main.js进程重启。依赖项swc/cli、swc/core、concurrently均已预置配合start:prod/start:debug脚本可覆盖生产启动与调试场景。服务入口 apps/api/src/main.ts 保持了 NestJS 标准的引导方式async function bootstrap() { const app await NestFactory.create(AppModule); app.enableCors(); await app.listen(3000); } void bootstrap();AppModuleapps/api/src/app.module.ts注册了LinksModule与根控制器/服务并开启了 CORS方便apps/web3001端口跨端口调用 API。六、远程缓存Remote Caching让 CI 与团队共享缓存默认情况下 Turborepo 只在本地缓存任务产物cache artifacts。启用 Vercel Remote Cache 后构建产物可以在本地与 CI 之间共享显著减少重复构建。启用步骤在仓库根目录执行pnpm turbo login pnpm turbo linklogin用于完成 Vercel 账号认证link则把当前仓库与远端缓存空间关联起来。之后每次pnpm build等任务的结果都会上传并可从远端命中。Vercel Remote Cache 对所有方案免费开放详见vercel.json与示例文档中的说明。提示pnpm turbo login/pnpm turbo link对应的是 Turborepo CLI 的login与link命令若只想用本地缓存这两步可以跳过。七、写在最后示例的学习路径with-nestjs的价值在于把NestJS 的装饰器生态与Turborepo 的任务编排/缓存机制完整地融合进一个可运行的最小 monorepo。继续深入时建议按以下顺序阅读仓库内容任务编排与缓存语义turbo.json → package.json → pnpm-workspace.yamlNestJS 侧实现apps/api/src/app.module.ts → apps/api/src/links/links.controller.ts → apps/api/src/links/links.service.ts共享资源与类型契约packages/api/src/entry.ts → packages/api/src/links/entities/link.entity.ts工程化配置packages/jest-config/src/nest.ts → packages/typescript-config/nestjs.json → packages/eslint-config端到端测试示例apps/api/test/app.e2e-spec.ts。此外Turborepo 还提供了其它官方示例如with-nextjs、with-vite、with-svelte、with-angular等均位于 examples 目录可作为不同技术栈组合的对照参考关于任务、缓存、过滤与 CLI 的通用概念可参阅本仓库根目录文档与 Turborepo 官方文档示例LinksService内置的三条链接也指向了安装、仓库编排与增量接入指南。以本项目为起点你可以在此基础上替换业务模块、接入数据库或将repo/api的类型契约扩展到前端逐步搭建生产级的全栈 monorepo。赞分享构建工具开发工具CLI【免费下载链接】turboBuild system optimized for JavaScript and TypeScript, written in Rust项目地址https://gitcode.com/gh_mirrors/tu/turbo点击查看免费下载相关推荐使用 Turborepo 搭建 Angular 多应用 Monorepowith-angular 示例深度解析使用 Turborepo 搭建 Angular 多应用 Monorepowith angular 示例深度解析 本文以本仓库中的 with angular 示构建工具开发工具CLI使用 Turborepo 构建 Svelte 5 SvelteKit monorepowith-svelte 示例深度解析使用 Turborepo 构建 Svelte 5 SvelteKit monorepowith svelte 示例深度解析 本篇技术指南以当前仓库中的 e构建工具开发工具CLI在 Turborepo Monorepo 中构建 NestJS APIwith-nestjs 示例应用实战指南在 Turborepo Monorepo 中构建 NestJS APIwith nestjs 示例应用实战指南 Turborepo 是专为 JavaScrip构建工具开发工具CLI创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考