Node Modules 模块系统
模块化
有过的解决方案:
- CMD/AMD/require.js
- CommonJS
- ES Module
nodejs 默认支持CommonJS
模块化,从版本 12.0.0 开始支持 ES Modules (ESM)。
CommonJS
导入
const variable = require('*');
导出
module.exports = {};
require
require 支持加载的类型:
.js
.json
.node
- 任何类型的文件,都会视为
.js
去解析
针对不同的文件类型,有不同的处理方式:
如果是
.js
文件,里面需要使用module.exports
或exports
输出一个模块。如果是
.json
文件,会使用JSON.parse
解析为 json 对象如果是
.node
文件,会使用process.dlopen
打开一个 C++插件
ES Module
导入:
import
导出:
export
Node 项目如何支持 ES Module
解决方案:
使用 webpack
通过 Node 原生支持(版本号大于 12.0.0)
1.使用 webpack
将ES Module
的语法转换成CommonJS
,打包成普通的 js 文件。
为了兼容低版本 node,需要使用bable
,如果使用了async/await
还需要添加@babel/plugin-transform-runtime
配置webpack.config.js
文件:
{
target: 'node', // 默认是web,需要改为node,去加载node内置库
}
2
3
2.通过 Node 原生支持
- 方案一:将
.js
文件后缀名改为.mjs
- 方案二:修改
package.json
文件 - 方案三:在文件的顶部添加 "type": "module" 的语句
.mjs
1. 方案一:修改后缀名为1.1 更改 js 文件后缀名为.mjs
1.2 import 的时候,不能省略后缀名
1.3 执行.mjs
文件
# node版本`>= v14`,可以直接执行
node ./bin/index.mjs
# or
# node版本低于`v14`,需要配置开启:`--experimental-modules`
node --experimental-modules ./bin/index.mjs
2
3
4
5
6
7
package.json
文件
2. 方案二:修改2.1 修改package.json
:
{
"type": "module"
}
2
3
默认将 js 文件全部转换为ES Module
模式,但是如果使用CommonJs
规范就需要把文件改为*.cjs
2.2 执行:
node ./bin/index.mjs
需要注意的几个点:
ES Module 中可以导入 CommonJs 模块
CommonJs 中不能导入 ES Module 模块
CommonJs 始终只会导出一个默认成员
注意 import 不能解构导出的对象
3. 方案三:在文件的顶部添加 "type": "module" 的语句
在 Node.js 中,使用 ES Modules 需要在文件的顶部添加 "type": "module" 的语句,表示该文件采用 ES Modules 格式。
// index.mjs
import { greet } from './module.js';
greet('world');
2
3
4
5
// module.js
export function greet(name) {
console.log(`Hello, ${name}!`);
}
2
3
4
5
在 Node.js 中,使用 ES Modules 还需要注意以下事项:
在 ESM 中,没有全局的 require() 函数和 module.exports 对象,所以需要使用 import 和 export 语法来加载和导出模块。
在 ESM 中,不能使用动态导入语法,例如 import('module.js'),只能使用静态导入语法,例如 import { x } from 'module.js'。
在 ESM 中,模块的路径必须是相对路径或绝对路径,不能使用模块标识符,例如 import fs from 'fs'。
全局包
使用
which node
查看全局软链接路径:/Users/cass/.nvm/versions/node/v16.16.0/bin/node
进入 bin 文件夹,使用
ls -la
可以查看到所有命令具体执行的文件
目录结构
bin
目录存放的是全局命令lib -> node_modules
目录存放的是全局包源码
模块的加载顺序
Node.js 模块的加载顺序是按照以下顺序来加载的:
首先,Node.js 会查找该模块是否已经被缓存,如果已经被缓存,则直接从缓存中加载。
如果没有被缓存,则按照模块的文件名来查找模块,如果文件名包含路径,则按照路径查找;否则,按照 Node.js 模块加载规则查找。
Node.js 模块加载规则是按照以下顺序查找模块:
3.1 先查找该模块是否是 Node.js 内置模块,如果是,则直接加载。
3.2 如果不是内置模块,则按照 NODE_PATH 环境变量和当前模块的 node_modules 目录查找该模块。
3.3 如果还没有找到该模块,则递归查找该模块的依赖模块。
模块的循环依赖
循环依赖是指两个或多个模块之间相互依赖的情况。在 Node.js 中,循环依赖会导致模块加载失败,因此需要谨慎处理循环依赖问题。可以通过延迟加载、重构代码和使用依赖注入等方式来解决循环依赖问题。