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