我们知道 nodejs 默认使用是 commonjs 模块导入导出方式
js
// 创建并导出模块
exports.foo = function() {
console.log('foo');
};
// 导入模块
var lib = require('./foo');
lib.foo(); // 调用
如果我们要使用 esm 模块导入方式
- 直接将文件后缀 .js 改成 .mjs (方式1)
- 在package.json 新增type字段
{ type: 'module' }
(方式2)
nodejs 使用 ts-node 执行 .ts 文件
如果我们使用ts-node运行 .ts 文件 , 可能会报 Unknown file extension ".ts" for xxx.ts
ts
// package.json
{
type: "module"
}
// foo.ts
export function foo(x: number): number {
return x * 2;
}
// test.ts
import { foo } from "./foo";
console.log(foo(1));
// 命令终端执行
npx ts-node ./test.ts //Unknown file extension ".ts" for xxx.ts
因为我们代码中使用的是esm 导入导出, 所以package.json 设置了 type: "module"
,这是很正常的事情,但原因在于ts-node 执行的时候, 先编译commonjs 模块的.js 文件, 然后用node 执行.js 文件, import 导入对 ts-node 来说没有实际功能作用, 只是一个标记符号。 所以这里设置的type:"module"
反而不对了, 要么删除type要么设置type:"commonjs"
js
// package.json
{
type: "commonjs"
}
// foo.ts
export function foo(x: number): number {
return x * 2;
}
// test.ts
import { foo } from "./foo";
console.log(foo(1));
// 命令终端执行
npx ts-node ./test.ts // Cannot use import statement outside a module
当我们把package.json 改成 type: "commonjs"
后又报 Cannot use import statement outside a module
, 这是因为ts-node 编译.ts 文件的时候会走 tsconfig.json 文件, 这个文件中有个编译选项 module: "ESNext"
ts
{
"compilerOptions": {
"module": "ESNext",
},
"include": ["src/"],
}
这就导致了 ts-node 编译成的 js 文件是 esm 模块化标准。但 ts-node 里面的 node 执行时依旧是以 commonjs 标准执行的
所以这里也要干掉 module: "ESNext"
或者改成module: "commonjs"
很多时候我们项目在用 tsconfig.json 文件, 但是我们要执行node ts脚本的时候配置项 module 会和 tsconfig.json 冲突了, 这个时候我们可以用ts-node 执行的ts 脚本的时候 手动指定一个自定义个 tsconfig.json 文件
bash
npx ts-node --project ./tsconfig.custom.json ./test.ts
这样基本就大功告成了。