构建兼容Node.js v20的TypeScript/MJS包:解决模块兼容报错
解决Node.js v20下TypeScript ES模块兼容问题
在开发@contoso/hello TypeScript包和web-hello Node.js应用时,遭遇三类模块兼容报错:
exports is not defined in ES module scopeUnexpected token 'export'TS1479: The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'
下面是针对性的配置调整方案:
1. 调整@contoso/hello包配置
修改package.json
添加"type": "module"声明为ES模块,补充exports字段明确入口,更新字段如下:
{ "name": "@contoso/hello", "version": "1.0.0", "type": "module", "main": "dist/index.js", "exports": "./dist/index.js", "types": "dist/index.d.ts", "scripts": { "build": "tsc", "prepublishOnly": "yarn build" }, "license": "ISC", "devDependencies": { "typescript": "^5.4.2", "@types/node": "^20.11.25" // 升级到与Node v20匹配的版本 }, "files": ["dist"] }
修改tsconfig.json
将模块系统设置为NodeNext,与Node.js的ES模块规范对齐:
{ "compilerOptions": { "target": "ESNext", "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "declaration": true, "sourceMap": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] }
2. 调整web-hello客户端应用配置
修改package.json
添加"type": "module"声明为ES模块,修正导入拼写错误:
{ "name": "web-hello", "version": "1.0.0", "description": "", "type": "module", "main": "dist/index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "tsc", "start": "node dist/index.js", "start:dev": "nodemon dist/index.js", "start:debug": "node --inspect-brk dist/index.js" }, "license": "ISC", "devDependencies": { "@types/express": "^4.17.21", "@types/node": "^20.11.25", "typescript": "^5.4.2" }, "dependencies": { "@contoso/hello": "^1.0.0", "express": "^4.18.3" } }
修改tsconfig.json
确保模块解析和包保持一致,生成符合ES模块规范的代码:
{ "compilerOptions": { "target": "ESNext", "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "./dist", "rootDir": "./src", "strict": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, "include": ["src/**/*"], "exclude": ["node_modules"] }
修正src/index.ts的导入拼写
import { sayHello } from '@contoso/hello'; // 修正拼写错误 import express from 'express'; const app = express(); const port = 3000; app.get('/say-hello', (req, res) => { res.send(sayHello()); }); app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`); });
关键修复说明
- 统一模块类型:包和客户端都声明为ES模块(
"type": "module"),避免Node.js默认按CommonJS解析ES模块代码导致的语法错误。 - 对齐模块解析:使用
NodeNext模块系统,让TypeScript生成完全符合Node.js ES模块规范的代码,解决CommonJS与ES模块的导入冲突。 - 明确入口路径:包的
exports字段帮助Node.js正确定位模块入口,避免解析歧义。 - 版本匹配:升级
@types/node到与Node.js v20兼容的版本,避免类型定义不匹配问题。
内容的提问来源于stack exchange,提问作者serge
相关产品推荐
相关产品推荐

