如何通过Turborepo在NestJS中正确引入Monorepo TypeScript包?
在Turborepo Monorepo中解决NestJS引入TypeScript公共包的语法错误
问题背景
用Turborepo搭建了包含NestJS应用和TS公共库的Monorepo,目录结构如下:
. ├── README.md ├── apps │ └── nest │ ├── README.md │ ├── nest-cli.json │ ├── package.json │ ├── src │ │ ├── app.controller.spec.ts │ │ ├── app.controller.ts │ │ ├── app.module.ts │ │ ├── app.service.ts <---- 在此引入lib中的类 │ │ └── main.ts │ ├── test │ │ ├── app.e2e-spec.ts │ │ └── jest-e2e.json │ ├── tsconfig.build.json │ └── tsconfig.json ├── package.json ├── packages │ └── lib │ ├── index.ts <------- 在此导出类 │ ├── package.json │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml └── turbo.json
在packages/lib/index.ts导出TypeScript类后,在apps/nest/src/app.service.ts中引入时触发语法错误:
nest:dev: nest:dev: [1:40:25 AM] Found 0 errors. Watching for file changes. nest:dev: nest:dev: /Users/hercule/Workspace/monorepo-nestjs-package/packages/lib/index.ts:3 nest:dev: public hello() { nest:dev: ^^^^^ nest:dev: nest:dev: SyntaxError: Unexpected identifier nest:dev: at Object.compileFunction (node:vm:360:18) nest:dev: at wrapSafe (node:internal/modules/cjs/loader:1088:15) nest:dev: at Module._compile (node:internal/modules/cjs/loader:1123:27) nest:dev: at Object.Module._extensions..js (node:internal/modules/cjs/loader:1213:10) nest:dev: at Module.load (node:internal/modules/cjs/loader:1037:32) nest:dev: at Function.Module._load (node:internal/modules/cjs/loader:878:12) nest:dev: at Module.require (node:internal/modules/cjs/loader:1061:19) nest:dev: at require (node:internal/modules/cjs/helpers:103:18) nest:dev: at Object.<anonymous> (/Users/hercule/Workspace/monorepo-nestjs-package/apps/nest/src/app.service.ts:2:1) nest:dev: at Module._compile (node:internal/modules/cjs/loader:1159:14)
注:该lib包在NextJS和Angular应用中可正常引入,仅NestJS出现此问题。
错误原因
核心问题是Node.js直接执行了未编译的TypeScript文件。NestJS默认仅编译自身src目录下的代码,不会处理Monorepo中packages目录的TS文件;而Next/Angular的构建工具默认会解析并编译项目依赖的本地TS包,因此能正常工作。
解决方案
1. 扩展NestJS的TypeScript编译范围
修改apps/nest/tsconfig.json,将packages目录加入编译范围,并配置路径别名:
{ "compilerOptions": { // 保留原有配置,新增路径别名 "paths": { "@your-lib/*": ["../../packages/lib/*"] // 替换为你的lib包名对应路径 } }, "include": [ "src/**/*", "../../packages/lib/**/*" // 新增:让TS编译时包含公共库代码 ], "exclude": ["node_modules", "dist"] }
同时更新apps/nest/tsconfig.build.json,确保构建时也包含公共库:
{ "extends": "./tsconfig.json", "exclude": ["node_modules", "test", "dist", "**/*spec.ts"], "include": ["src/**/*", "../../packages/lib/**/*"] }
2. 配置公共lib包的编译规则
调整packages/lib/package.json,设置正确的入口、类型声明,并添加编译脚本:
{ "name": "@your-lib", // 需与上述路径别名中的名称一致 "version": "0.0.1", "main": "./dist/index.js", // 编译后的JS入口 "types": "./dist/index.d.ts", // 类型声明文件路径 "scripts": { "build": "tsc", // 添加TS编译命令 "dev": "tsc --watch" // 可选:监听文件变化自动编译 } }
确保packages/lib/tsconfig.json指定了输出目录:
{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "declaration": true, "outDir": "./dist", // 指定编译产物输出到dist目录 "rootDir": "./", "strict": true, "esModuleInterop": true }, "include": ["index.ts"] }
3. 配置TurboRepo任务依赖
修改turbo.json,让Nest的开发任务依赖公共库的编译任务,确保启动Nest前先编译lib:
{ "$schema": "https://turbo.build/schema.json", "globalDependencies": ["**/.env.*local"], "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] }, "dev": { "cache": false, "dependsOn": ["^dev"] // 让nest的dev任务依赖lib的dev任务 } } }
4. 验证启动
执行pnpm i安装依赖后,运行pnpm dev,Turbo会先启动公共库的监听编译,再启动NestJS开发服务,此时引入公共库的类即可正常工作。
内容的提问来源于stack exchange,提问作者SugarMouse
相关产品推荐
相关产品推荐

