模块化系统
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 |
