news 2026/10/15 2:40:19

【node.js】node.js 两种模块规范 CommonJS 和 ESM 如何选择?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【node.js】node.js 两种模块规范 CommonJS 和 ESM 如何选择?

在 Node.js 的生态系统中,存在两种主要的模块规范:CommonJS (CJS)和ES Modules (ESM)。

理解它们的区别对于现代前端和后端开发至关重要,因为 Node.js 正在从 CJS 全面转向 ESM。


1. CommonJS (CJS)

CommonJS 是 Node.js 诞生的默认模块系统,已经存在了十多年。

  • 语法:使用require()导入模块,使用module.exports导出模块。
  • 加载方式:同步加载。这意味着当你调用require()时,Node.js 会阻塞后续代码的执行,直到模块加载完成。
  • 适用场景:传统 Node.js 项目、服务器端脚本。

示例代码:

// 导出 (math.js)constadd=(a,b)=>a+b;module.exports={add};// 导入 (main.js)const{add}=require('./math.js');console.log(add(2,3));

2. ES Modules (ESM)

ESM 是 JavaScript 在 2015 年(ES6)确立的标准官方模块系统,旨在让浏览器和服务器通用一套标准。

  • 语法:使用import导入,使用export导出。
  • 加载方式:异步加载。它分为三个阶段:构建(解析)、链接、求值。这种机制支持“静态分析”。
  • 适用场景:现代前端框架(Vue, React)、浏览器环境、现代 Node.js 项目。

示例代码:

// 导出 (math.js)exportconstadd=(a,b)=>a+b;// 导入 (main.js)import{add}from'./math.js';console.log(add(2,3));

3. 核心区别对比

特性CommonJS (CJS)ES Modules (ESM)
关键字require/module.exportsimport/export
加载时机运行时加载。编译时加载(静态分析)。
加载方式同步。异步。
顶层变量有__dirname,__filename。没有这些变量(需用import.meta.url模拟)。
this 指向指向当前模块。undefined。
Tree Shaking不支持(因为是动态加载)。支持(可以删除未使用的代码)。
严格模式默认不开启。强制开启(“use strict”)。

4. 关键差异深度解析

(1) 静态分析 vs 动态加载
  • ESM 是静态的:import语句必须放在文件顶部。因为它是静态的,打包工具(如 Webpack, Rollup, Vite)可以在代码运行前知道哪些代码被使用了,从而进行Tree Shaking(剔除无效代码),缩小包体积。
  • CJS 是动态的:你可以在if语句或函数内部写require()。这使得它很灵活,但也无法在编译阶段进行优化。
(2) 值的拷贝 vs 值的引用
  • CJS:导出的是值的拷贝。一旦输出一个值,模块内部的变化不会影响到已加载的值。
  • ESM:导出的是值的动态只读引用(Live Bindings)。如果模块内部修改了变量,外部引用的地方也会同步更新(但外部不能修改它)。
(3) 环境变量(__dirname)

在 CJS 中,你可以直接使用__dirname获取当前目录。在 ESM 中,这些全局变量不存在,你需要这样操作:

// ESM 获取 __dirname 的方法import{fileURLToPath}from'url';import{dirname}from'path';const__filename=fileURLToPath(import.meta.url);const__dirname=dirname(__filename);

5. 如何在 Node.js 中选择?

现在 Node.js 同时支持两者,判断规则如下:

  1. 文件名后缀:
    • .cjs总是被视为 CommonJS。
    • .mjs总是被视为 ES Modules。
    • .js取决于最近的package.json。
  2. package.json:
    • 设置"type": "module",则.js文件被视为ESM。
    • 设置"type": "commonjs"或不设置,则.js文件被视为CJS。

6. 互操作性(能不能混用?)

  • ESM 导入 CJS:可以。import cjs from './file.cjs'通常能工作,但只能默认导入,不能通过解构导入(因为 CJS 是运行时生成的)。
  • CJS 导入 ESM:不可以使用require()。因为 ESM 是异步的,而require是同步的。如果必须在 CJS 中用 ESM,只能使用异步的import()函数:
    // 在 CJS 文件中import('./esm-file.mjs').then(module=>{// 使用模块});

总结

  • 如果你正在开发新项目,建议优先使用ESM,因为它是未来的标准,且支持更好的性能优化。
  • 如果你在维护老旧项目或使用大量仅支持 CJS 的老旧库,则继续使用CommonJS。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 15:35:26

Excalidraw在Chrome/Firefox/Safari上的表现差异

Excalidraw在Chrome/Firefox/Safari上的表现差异 如今,远程协作早已不是“未来趋势”,而是每个技术团队的日常现实。无论是画一张微服务架构图、梳理产品流程,还是快速勾勒一个UI原型,Excalidraw 凭借其手绘风格的亲和力与轻量级的…

作者头像 李华
网站建设 2026/10/14 4:22:17

19、Windows Server 2003 WMI:安全改进与服务管理

Windows Server 2003 WMI:安全改进与服务管理 1. Microsoft安全举措对WMI脚本编写者的影响 2002年初,微软发起了一项重大的安全倡议,旨在增强Windows平台的安全性。该倡议要求所有微软开发人员对其代码进行审查,以排查可能导致现有操作系统安全漏洞的潜在问题。这意味着在…

作者头像 李华
网站建设 2026/10/15 2:43:38

Excalidraw群组与锁定功能使用场景解析

Excalidraw群组与锁定功能使用场景解析 在一场远程架构评审会议中,团队成员正围绕一张云平台拓扑图展开讨论。突然,某位同事不小心拖动了一个微服务模块,导致整个系统布局错乱——连接线断裂、层级关系混乱,几分钟的沟通成果瞬间被…

作者头像 李华
网站建设 2026/10/14 15:22:50

Excalidraw反向代理Nginx配置样例

Excalidraw 反向代理 Nginx 配置实践指南 在现代远程协作日益频繁的背景下,团队对轻量级、高自由度的在线白板工具需求持续增长。Excalidraw 凭借其手绘风格的视觉表达和出色的实时协作能力,逐渐成为技术设计、架构讨论和教学演示中的热门选择。然而&…

作者头像 李华
网站建设 2026/10/14 17:33:17

21、深入探索ADSI:管理Windows目录服务的利器

深入探索ADSI:管理Windows目录服务的利器 1. 引言 在Windows环境中,活动目录(Active Directory)以及本地计算机安全账户管理器(SAM)中的本地“目录”是至关重要的组成部分。许多与目录相关的任务,对于Windows管理员来说,是既耗时又重复的工作。而脚本化则成为了一种有…

作者头像 李华
网站建设 2026/10/14 18:20:20

24、深入了解 WMI:功能、使用与脚本编写指南

深入了解 WMI:功能、使用与脚本编写指南 1. WMI 概述 WMI(Windows Management Instrumentation)并非 Windows 操作系统的核心组成部分,而是运行在 Windows 上的一组附加服务。在 Windows 2000 及更高版本的计算机中,可在服务控制面板里看到该服务。Windows 没有 WMI 也能…

作者头像 李华