Node.js 文件执行
2026/5/13大约 2 分钟
一句话结论
Node.js 执行文件时先判断模块格式,再交给对应加载器运行。.js 会受最近的 package.json type 字段影响,.cjs 永远按 CommonJS,.mjs 永远按 ES Module。
为什么需要它
- 场景:本地运行脚本、发布 CLI、迁移 ESM、执行 TypeScript 文件。
- 不处理会怎样:
import、require、__dirname、import.meta.url混用后容易出现语法错误或运行时错误。
运行时边界
| 文件 | Node.js 行为 | 备注 |
|---|---|---|
.js | 跟随最近 package.json 的 type | 默认 CommonJS |
.cjs | CommonJS | 不受 type 影响 |
.mjs | ES Module | 不受 type 影响 |
.ts | 取决于 Node 版本和运行方式 | 项目中通常用 tsx、ts-node 或先 tsc |
Node.js 的模块判断是运行时加载规则,不是 TypeScript 类型系统规则。
核心概念
| 概念 | 含义 | 备注 |
|---|---|---|
| CommonJS | require / module.exports | 历史包生态广泛使用 |
| ES Module | import / export | 标准模块系统 |
type | package.json 的模块类型声明 | 影响 .js |
| 入口文件 | 传给 node 命令的文件 | 如 node src/index.js |
实现
执行 JavaScript 文件
node index.js
node index.cjs
node index.mjs当项目没有 package.json,或最近的 package.json 没有 "type": "module" 时,.js 默认按 CommonJS 处理。
{
"type": "module"
}设置后,同一目录树下的 .js 会按 ES Module 处理,除非文件扩展名是 .cjs。
执行 TypeScript 文件
生产构建更推荐先编译:
npx tsc -p tsconfig.json
node dist/index.js本地脚本可用运行器:
npx tsx scripts/build.tstsx 适合开发和脚本执行,但默认不等同于完整类型检查。CI 仍应单独运行:
npx tsc --noEmit边界与常见坑
__dirname只在 CommonJS 中直接存在:ESM 中用import.meta.url配合fileURLToPath。require不能直接加载 ESM:优先使用动态import()或迁移调用方。type只影响.js:.cjs和.mjs是强制扩展名。- 执行 TS 不等于类型检查:运行器为了速度可能跳过类型检查。
工程取舍
- 适合:
.cjs/.mjs明确跨模块边界,避免歧义。 - 谨慎:在同一个包里混用两套模块系统。
- 不适合或应换方案:生产环境直接依赖临时 TS 运行器,应优先构建后运行。
面试 / 自测
.js如何判断是 CJS 还是 ESM?.cjs和.mjs是否受package.jsontype影响?- 为什么
tsx运行通过不代表类型检查通过?
