Turborepo Monorepo中TypeScript编译私有Prisma包问题排查
NestJS引入Monorepo私有database包时的SyntaxError问题分析与解决
问题根因
你的NestJS后端采用commonjs模块规范(见tsconfig/server.json中module: "commonjs"配置),而database私有包的入口代码是ES模块语法的export * from "@prisma/client",且该包未预先编译为CommonJS格式。
NestJS默认使用tsc编译,它会跳过node_modules目录下的文件(即使是Monorepo中软链接的私有包),导致后端运行时直接读取未编译的ES模块代码,Node.js在CommonJS环境下无法识别export语法,因此抛出SyntaxError: Unexpected token 'export'。
为什么前端NextJS可以正常使用?
NextJS的编译链(基于Webpack/SWC)对Monorepo做了针对性优化:
- 自动识别本地私有包的未编译TS/ES源码,并将其纳入编译流程,转译为浏览器兼容的格式。
- NextJS的
tsconfig配置module: "esnext",本身天然支持ES模块语法,无需额外处理即可直接识别database包的代码。
解决方案
方案1:预先构建database包(推荐)
给database包添加编译流程,输出同时支持CommonJS和ES模块的双格式,适配前后端不同的模块规范:
- 添加database包的tsconfig.json:
{ "$schema": "https://json.schemastore.org/tsconfig", "extends": "../tsconfig/base.json", "compilerOptions": { "target": "es2017", "module": "commonjs", "declaration": true, "outDir": "./dist", "strict": true, "skipLibCheck": true }, "include": ["index.ts"], "exclude": ["node_modules"] }
- 配置database包的package.json:
指定编译后的入口文件、类型文件,并添加构建脚本:
{ "name": "@your-org/database", "private": true, "main": "./dist/index.js", "module": "./dist/index.mjs", // 可选,输出ES模块格式适配前端 "types": "./dist/index.d.ts", "scripts": { "build": "tsc && tsc --module esnext --outDir dist/esm && mv dist/esm/index.js dist/index.mjs" } }
- 用Turborepo管控构建依赖:
在根目录的turbo.json中配置流水线,确保后端构建前先完成database包的构建:
{ "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] }, "dev": { "cache": false, "dependsOn": ["^dev"] } } }
方案2:让NestJS编译时转译database包
修改后端的tsconfig.json,将database包纳入编译范围(不推荐,容易引发路径和编译冲突):
{ "extends": "tsconfig/server.json", "compilerOptions": { "outDir": "./dist", "baseUrl": "./", }, "include": ["**/*.ts", "../../node_modules/@your-org/database/**/*.ts"], "exclude": ["node_modules/**/*", "!../../node_modules/@your-org/database/**/*.ts"] }
注意:路径需根据你的Monorepo结构调整,且这种方式可能导致编译速度变慢、类型冲突等问题。
方案3:修改database包为CommonJS语法(不推荐)
将database包的入口代码改为CommonJS格式:
module.exports = require("@prisma/client");
此方案会导致前端使用时需要处理CommonJS转ES模块的兼容问题,破坏前端的ES模块生态,因此不推荐。
内容的提问来源于stack exchange,提问作者Robert Tirta
相关产品推荐
相关产品推荐

