如何在ESM模式的TypeScript项目中使用非相对路径导入?
如何在ESM模式的TypeScript项目中使用非相对路径导入?
兄弟,我太懂你这种搜了好几个小时找不到解决方案的崩溃了!之前用CommonJS的时候靠NODE_PATH就能随便用非相对路径导入模块,结果切到ESM模式直接失效,确实让人头大。我来给你一步步捋清楚怎么搞定这个问题。
首先先明确下你的项目场景,方便对照:
- 项目结构
src/ app.ts test/ test.ts package.json - 业务代码
src/app.ts:
src/test/test.ts:import machin from 'test/test'; console.log('This is the app'); machin();export default function machin() { console.log('This is the test !'); } - 原CommonJS模式下的package.json(靠
NODE_PATH实现非相对导入):{ "name": "test", "version": "0.0.1+dev", "type": "commonjs", "main": "dist/app.js", "scripts": { "start": "if [ \"${NODE_ENV}\" = production ]; then npm run start:prod; else npm run start:dev;fi", "start:prod": "NODE_PATH=src/ node src/app.js", "start:dev": "npm run build && NODE_PATH=dist/src/ node dist/src/app.js" } }
核心问题:ESM不支持NODE_PATH
Node.js的ESM模块系统不再识别NODE_PATH环境变量,原来的方法直接作废。我们需要结合TypeScript的配置和ESM特性来解决,分三步走:
第一步:切换项目到ESM模式
在package.json里添加"type": "module",告诉Node.js这是一个ESM项目:
{ "name": "test", "version": "0.0.1+dev", "type": "module", // 关键:切换到ESM模式 "main": "dist/app.js", "scripts": { // 后续更新脚本 } }
第二步:配置TypeScript识别非相对路径
修改tsconfig.json,通过baseUrl和paths让TypeScript编译器能解析非相对路径:
{ "compilerOptions": { "target": "ESNext", "module": "ESNext", "moduleResolution": "NodeNext", // 必须,适配ESM的模块解析逻辑 "baseUrl": "./src", // 把src目录作为模块查找的基础路径 "paths": { "*": ["*"] // 匹配所有非相对路径,从baseUrl开始查找 // 若只想针对特定前缀配置,比如"test/*": ["test/*"]也可 }, "outDir": "./dist", // 编译产物输出到dist目录 "strict": true, "esModuleInterop": true }, "include": ["src/**/*"] // 包含src下所有文件 }
这一步完成后,TypeScript编译器就不会再报“找不到模块”的错误了。
第三步:处理运行时的模块解析
TypeScript编译后,Node.js本身还是无法识别我们配置的非相对路径,这里推荐两种最省心的解决方案:
方案1:用tsx直接运行(推荐)
tsx是能直接运行TypeScript文件的工具,它会自动读取tsconfig.json里的paths配置,完美适配ESM。
- 先安装依赖:
npm install -D tsx - 修改
package.json的scripts:
生产环境编译后,需确保"scripts": { "start": "if [ \"${NODE_ENV}\" = production ]; then npm run start:prod; else npm run start:dev;fi", "start:dev": "tsx src/app.ts", // 直接用tsx运行源码 "start:prod": "npm run build && node dist/app.js", // 编译后用node运行 "build": "tsc" }dist目录下的模块路径能被Node.js识别,可配合package.json的exports字段映射:
在package.json里添加:
这样编译后"exports": { "./test/*": "./dist/test/*" }import 'test/test'就会被解析到dist/test/test.js。
方案2:用ts-node-esm + tsconfig-paths
如果你习惯用ts-node,可以搭配tsconfig-paths处理路径映射:
- 安装依赖:
npm install -D ts-node tsconfig-paths - 修改
start:dev脚本:
这种方式需注意版本兼容性,偶尔会有小坑,所以更推荐第一种方案。"start:dev": "NODE_OPTIONS='--loader ts-node/esm --require tsconfig-paths/register' ts-node src/app.ts"
按照上面的步骤配置完,你就能在ESM模式的TypeScript项目里愉快地使用非相对路径导入了!
备注:内容来源于stack exchange,提问作者Nathanaël Spriet
相关产品推荐
相关产品推荐

