Skip to content

模块化系统

CommonJS(CJS)模块系统

使用module.exports或者exports导出模块代码 外部使用require导入模块

ES Modules(ESM)模块系统

ESM是在 ECMAScript 6 (ES2015/ES6) 中引入的一项重要特性,旨在取代 CommonJS 和 AMD 规范,成为 JavaScript 模块化的主要标准。

与CJS的区别

ESM 模块的导入和导出遵循 ECMAScript 官方规范,与 CJS 不同。ESM 模块的导入使用 import 关键字,导出使用 export 关键字。

默认情况下 Node.js 会将 .js 后缀文件识别为 CJS 模块。

在 Node.js 中正确工作

要让 Node.js 正确识别,主要有两种方式:

  • 使用 .mjs 作为文件后缀名 (例如 hello.mjs);
  • package.json 中 type 字段设置为 module

导入导出

导入导出的三种方式:

1. 默认导入导出

导出使用 export default 关键字。 导入import xx from 'module'

2. 具名导入导出

具名导出,使用 export 关键字。 导入指定具名内容。import { xx } from 'module'

实用 as 关键字还可以修改导入内容的名称。

3. 导入导出所有对象

可以将另一个模块的内容直接全部导出。 导出同时也可以设置默认导出。 export *

使用 import * as xx from 'module' 导入所有内容。

CJS 和 ESM之间的一些区别

1. 模块加载时机

  • CJS 支持动态加载模块 (require 语句可以出现在任意位置);
  • ESM 会在所有模块都加载完毕后才执行代码 (通常会将import导入语句放在模块的顶部);

ESM 是静态解析的,它会在编译时首先解析模块中的导入语句,虽然通常会将导入语句放在模块的顶部,但并不是要求所有的 import 语句必须在文件顶部,只要在使用导入的内容之前进行导入即可。 因此 ESM 可以在代码执行前进行静态分析和优化,从而提高性能 (比如自动移除无用的死代码)。 而 CJS 需要等到代码运行时才能确定依赖关系和加载模块。

2. 导出内容的区别

在 ESM 中,当我们导入一个变量时,实际上是导入了该变量的引用。这意味着,如果导出的变量在导入模块中发生了改变,导入的变量也会随之改变。

而在 CommonJS 中,导入的是导出模块的值的拷贝,而不是引用。这意味着,即使导出模块中的值发生了改变,导入模块中导入的变量不会受到影响。

简而言之,ESM 导入的是值的引用,而 CJS 导入的是值的拷贝。

3. 文件命名

一般都以 .js 结尾,通过 package.json"type":"module" 区分模块加载类型,也可以通过文件命名来区分 .cjs 表明是 CJS 规范的模块,.mjs 表明是 ESM 规范的模块。

常用的内置模块

Node.js提供了许多内置模块,这些内置的模块支持调用系统能力,如文件操作、网络通信等,通过组合这些基础的能力,就能完成复杂任务的执行。

模块名称说明
global全局对象,挂载了一些常用方法和属性
path提供与文件路径相关的实用工具方法
fs文件系统模块,用于操作文件和目录
util提供一些实用工具函数
http用于创建 HTTP 服务器,也可用于向已有服务发起请求并获取响应
child_process用于创建操作子进程
其它常用的工具模块url,Timers,Readline,crypto

上次更新于: