You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js 20.9.0 LTS下如何用ts-node运行带ESM支持的TypeScript?

升级Node.js到20.9.0 LTS后TypeScript+Express项目运行错误解决

问题背景

将Node.js从18升级至20.9.0 LTS后,运行基于TypeScript+Express的项目时出现模块兼容错误,相关配置及报错信息如下:

项目配置

package.json

{
  "name": "myproject",
  "version": "1.0.0",
  "private": "true",
  "license": "UNLICENSED",
  "main": "dist/index.js",
  "scripts": {
    "dev": "NODE_ENV=development nodemon",
    "dev-lite": "NODE_ENV=development node --loader ts-node/esm src/index.ts",
  },
  "dependencies": {},
  "devDependencies": {}
}

tsconfig.json

{
  "compilerOptions": {
    "module": "CommonJS",
    "esModuleInterop": true,
    "target": "ES6",
    "noImplicitAny": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "strict": true,
    "paths": {
      "*": ["node_modules/*"]
    }
  },
  "include": ["src/**/*"]
}

报错信息

  1. 初始运行yarn dev-lite时报错:
yarn run v1.22.19
$ NODE_ENV=development node --loader ts-node/esm src/index.ts
(node:12820) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("ts-node/esm", pathToFileURL("./"));'
(Use `node --trace-warnings ...` to show where the warning was created)
(node:12820) 警告:若要加载ES模块,请在package.json中设置"type": "module"或使用.mjs扩展名。
(node:12820) 警告:若要加载ES模块,请在package.json中设置"type": "module"或使用.mjs扩展名。
/home/mumin/welcome_localdev/sc-graphql-store-writer/src/index.ts:1
import app from './app';
^^^^^^

SyntaxError: 无法在模块外部使用import语句
  at internalCompileFunction (node:internal/vm:73:18)
  at wrapSafe (node:internal/modules/cjs/loader:1153:20)
  at Module._compile (node:internal/modules/cjs/loader:1205:27)
  at Module._extensions..js (node:internal/modules/cjs/loader:1295:10)
  at Module.load (node:internal/modules/cjs/loader:1091:32)
  at Module._load (node:internal/modules/cjs/loader:938:12)
  at cjsLoader (node:internal/modules/esm/translators:284:17)
  at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:234:7)
  at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
  at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)

Node.js v20.9.0
error Command failed with exit code 1.
  1. 添加"type": "module"到package.json后新报错:
yarn run v1.22.19
$ NODE_ENV=development node --loader ts-node/esm src/index.ts
(node:21831) ExperimentalWarning: `--experimental-loader` may be removed in the future; instead use `register()`:
--import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register("ts-node/esm", pathToFileURL("./"));'
(Use `node --trace-warnings ...` to show where the warning was created)
file:///home/mumin/welcome_localdev/sc-graphql-store-writer/src/index.ts:5
Object.defineProperty(exports, "__esModule", { value: true });
                      ^

ReferenceError: ES模块作用域中未定义exports
    at file:///home/mumin/welcome_localdev/sc-graphql-store-writer/src/index.ts:5:23
    at ModuleJob.run (node:internal/modules/esm/module_job:217:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:316:24)
    at async loadESM (node:internal/process/esm_loader:34:7)
    at async handleMainPromise (node:internal/modules/run_main:66:12)

Node.js v20.9.0
error Command failed with exit code 1.

尝试将tsconfig.json的"module"改为"Node16"或"ESNext"后,仍出现相同的ReferenceError。


解决方案

1. 统一ES模块配置

核心是让TypeScript编译输出与Node.js的ES模块规则完全对齐:

修改package.json

  • 保留"type": "module",添加ts-node的ES模块专属配置
  • 替换--experimental-loader为Node.js 20推荐的--import参数
{
  "name": "myproject",
  "version": "1.0.0",
  "private": "true",
  "license": "UNLICENSED",
  "main": "dist/index.js",
  "type": "module",
  "ts-node": {
    "esm": true,
    "experimentalSpecifierResolution": "node"
  },
  "scripts": {
    "dev": "NODE_ENV=development nodemon",
    "dev-lite": "NODE_ENV=development node --import ts-node/esm src/index.ts"
  },
  "dependencies": {},
  "devDependencies": {}
}

修改tsconfig.json

调整编译选项适配ES模块:

{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "NodeNext",
    "target": "ES2020",
    "noImplicitAny": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"]
}
  • module和moduleResolution设为ESNext/NodeNext,确保输出ES模块并遵循Node.js解析规则
  • 提升target到ES2020,匹配Node.js 20的原生支持范围

2. 统一代码中的模块语法

检查项目所有文件,将CommonJS语法替换为ES模块语法:

  • 替换module.exports = xxx为export default xxx
  • 替换exports.xxx = yyy为export const xxx = yyy

3. 更新依赖版本

确保ts-node和typescript为最新版本,避免旧版本的兼容性问题:

yarn add -D ts-node@latest typescript@latest

4. 适配nodemon(可选)

如果使用yarn dev命令,创建nodemon.json配置文件支持ES模块:

{
  "watch": ["src"],
  "ext": "ts",
  "exec": "NODE_ENV=development node --import ts-node/esm src/index.ts"
}

内容的提问来源于stack exchange,提问作者Muminur Rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 04:47:02