Node.js 模块系统:CJS 与 ESM 详解
文章目录前言一、CommonJS (CJS)二、ESMES Module三、跨模块互相导入重要坑点四、有关路径的要求总结前言Node.js 两套模块系统CommonJS(CJS)、ESM由package.json和文件后缀共同决定。JavaScript 最初没有模块系统Node.js 诞生后自行实现 CommonJSrequire/module.exports用于服务端并非语言官方标准。随后ES6 推出官方标准 ESMimport/export支持浏览器与 Node支持静态分析但 Node 为兼容海量旧生态没有直接替换 CommonJS。于是 Node 两套模块共存依靠package.json type和文件后缀.mjs/.cjs区分由此产生各类导入语法差异。一、CommonJS (CJS)要求如下package.json: “type”: “commonjs” 默认值不写type也是CJS文件后缀.js - CJS; .cjs - 强制 CJS无视package.json语法require() / module.exports不能用import/export导出helpers.js// 方式1整体导出对象最常用module.exports{func1,func2};// 方式2逐个挂载exports.func1func1;exports.func2func2;导入main.js// ✅ 本地文件必须 ./ 开头后缀 .js 可以省略建议写上const{func1,func2}require(./helpers.js);// ❌ 错误不带 ./node会去node_modules查找npm包const{func1}require(helpers);require(./helpers)省略后缀也可以Node 自动补.js/.json。只能用.js后缀不能命名为.mjs。运行命令node main.js二、ESMES Modulepackage.jsontype:module文件后缀.mjs→ 强制 ESM完全忽略 package.json 的 type 配置语法import / export原生不能直接用require()重点.mjs永远 ESM.cjs永远 CJS普通.js看package.json的type字段。导出helpers.js:// 方式1声明时直接导出exportasyncfunctionloadPackage(){}// 方式2末尾集中导出export{loadPackage};// 默认导出exportdefault{loadPackage};导入main.mjs:// ✅本地文件必须 ./ 开头**后缀 .js 不能省略ESM不会自动补后缀**import{loadPackage}from./helpers.js;// 如果导入的是CJS模块helpers.js是module.exports也可以default导入importhelpersfrom./helpers.js;const{loadPackage}helpers;// ❌错误1无 ./当作npm包import{loadPackage}fromhelpers;// ❌错误2省略后缀ESM直接报模块找不到import{loadPackage}from./helpers;当文件是.mjs就算 package.json 是commonjs依然执行 ESM 语法。运行node generateTestcase.mjs三、跨模块互相导入重要坑点ESM (.mjs) 导入 CJS (.js):允许CJS 的module.exports对象被 ESM 识别支持解构导入。import{loadPackage}from./helpers.js;// 结构导入// 或者使用CJS的原生require导入import{createRequire}frommodule;constrequirecreateRequire(import.meta.url);// Enable require in ESMconstpkgrequire(pkgPath);CJS 导入 ESMCJS 的require()不能直接 require ESM 文件会报错只能用动态await import()。// CJS里面加载ESM模块只能动态importconstesmModuleawaitimport(./some-esm.js);四、有关路径的要求ESM 动态导入await import其路径必须是file://开头的 URL 字符串指向本地磁盘文件。不接受windows系统的反斜杠。// ✅ 本地磁盘文件必须转成file:// URLconsturlpathToFileURL(absDiskPath).href;constmodawaitimport(url);constabsFsPathC:\\Users\\LIly\\file.js;// path.resolve得到带反斜杠 const url pathToFileURL(absFsPath).href; // ✅API内部自动处理反斜杠 → file:///C:/... const mod await import(url);awaitimport(./dir/test.js);// ✅ 只能正斜杠 await import(./dir\\test.js);// ❌ 反斜杠不行同静态import// Windows反斜杠转换functionnormalizeSlash(p){if(isWindows()){returnp.replace(/\\/g,/);}returnp;}ESM 静态导入 import xxx from “xxx”静态导入不接受 file:// URL也不接受操作系统磁盘绝对路径C:\xxx /home/xxx。不接受Windows的反斜杠。静态导入只有两类合法输入裸模块名npm 包、node 内置模块lodash、fs/promisesimportxfromlodash相对说明符./xxx.js、…/xxx.jsimportxfrom./dir\\test.js;// ❌错误\是字符串转义符号路径直接错乱importxfrom./dir/test.js;// ✅只能正斜杠 /require的动态导入操作系统原生磁盘路径完全接纳 Windows 反斜杠\唯一坑给 require 的相对本地文件路径必须带上./或者../否则会被识别成npm包。letpath./helper.js;constmrequire(path);// ✅完全合法if(flag){require(./other.js)}总结Node.js 中 CJS 与 ESM 双模块系统共存核心区分逻辑是package.json的type字段 文件后缀.mjs/.cjsCJSrequire/module.exportstype: commonjs或默认require对本地文件路径带./后缀.js可省略。ESMimport/exporttype: module或.mjs后缀强制import必须写./且后缀不可省略。跨模块导入ESM 导入 CJS 一般没问题支持解构导入反过来 CJS 用require加载 ESM 会直接报错必须用动态await import()。日常开发先确认项目根目录package.json的type再决定用哪个文件后缀和导入语法可以避免绝大多数模块解析错误。导入方式类型执行时机静态 / 动态路径完整要求Windows 反斜杠支持相对路径要求CommonJSrequire()运行时函数调用执行到该行才加载✅动态导入1. npm 包直接写包名2. 本地文件操作系统原生磁盘路径不需要 file:// 协议✅兼容\与/本地相对文件必须带.//../不带则识别为 npm 包后缀可省略ESM 静态导入import xxx from xxxJS 语法解析阶段代码运行前✅静态导入1. npm 包直接写包名2. 本地文件仅允许.//../相对说明符禁止 file://、禁止磁盘绝对路径只能字符串字面量不能变量❌禁止\只能正斜杠/必须.//../前缀必须写完整.js后缀不可省略ESM 动态导入await import(xxx)Promise 函数调用执行到该行才加载✅动态导入1. npm 包直接写包名2. 本地磁盘文件必须传入file://URL不能直接传操作系统磁盘路径支持变量传参❌不要手动处理\原始磁盘路径交给pathToFileURL()自动转 URL字面量写./xxx.js规则同静态导入变量加载本地文件必须转为file://

相关新闻

DAQ 不是“慢速示波器”,它解决的是另一类问题

DAQ 不是“慢速示波器”,它解决的是另一类问题

当问题不再发生在纳秒级,而是表现为几小时、几天甚至更长尺度上的变化时,DAQ 的价值才真正显现。 DAQ 面向多通道、长时间的系统级测量(图片来源:DigiKey)摘要:很多人把 DAQ 理解成“采样慢一点、记录久一点…

2026/11/4 5:42:42 阅读更多 →
AI总结幻觉:三大类型拆解与可落地的检测缓解方案

AI总结幻觉:三大类型拆解与可落地的检测缓解方案

1. 从一次真实的“翻车”现场说起上周,我们团队内部评审一个即将上线的智能文档分析功能。产品经理信心满满地演示:用户上传一份50页的行业研究报告,我们的AI助手能在30秒内生成一份结构清晰、要点突出的千字摘要。演示很顺利,摘要…

2026/11/13 6:35:26 阅读更多 →
AI辅助编程实战:用Python与Pygame开发经典贪吃蛇游戏

AI辅助编程实战:用Python与Pygame开发经典贪吃蛇游戏

1. 项目概述:当经典游戏开发遇上AI助手 最近几年,AI编程工具的发展速度确实让人惊讶。作为一名有十多年编程经验的开发者,我最初对这类工具的态度是怀疑的——它们能写出真正可用的代码吗?会不会只是生成一些华而不实的“玩具”&a…

2026/11/12 15:25:42 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/14 5:13:29 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/14 5:13:29 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/14 5:13:29 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/13 22:08:41 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/14 2:41:37 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/14 5:13:29 阅读更多 →

日新闻

周新闻

月新闻