nodeJs 模块机制
在讲模块机制之前,先来说说 CommonJs 规范,我们知道在打包的时候经常会看到 cjs 这个选项,这里的 cjs,我自己之前是一直以为就是commonJs,实际上这是 node 对 CommonJs 的实现,是 node 的模块机制。
ComonJs 规范范围除了模块规范之外,还有二进制、Buffer、字符集编码、I/O 流、进程环境、文件系统、套接字、单元测试、Web 服务器网关接口以及包管理等规范。
既然 node 模块机制是 CommonJs 的一种实现,那么 CommonJs 的模块规范是怎样的呢?CommonJs 的模块规范主要做了如下定义:
模块引用:通过 require 引入模块
模块定义:module 对象代表模块自身,通过 exports 属性导出当前模块的变量或对象
模块标识:必须是符合小驼峰命名的字符串,或者是文件路径(相对路径、绝对路径)
接下来讲讲 nodeJs 的模块机制是怎么实现的,当我们用 require 引入某个模块时,会经历以下三个过程:路径分析,文件定位以及编译执行。再来讲讲每个步骤分别发生了什么。
路径分析
核心模块,加载速度快,加载优先级仅次于缓存加载
路径形式的文件模块:把路径转换为真实路径
自定义模块:沿当前路径往上逐级递归查找,最深可以查找到根目录下的 node_modules,由于路径查找速度比较慢,所以加载速度也会比较慢
基于以上因素,为提高模块加载速度,在模块引入时,引入顺序应该为:核心模块 -> 路径形式的文件模块 -> 第三方模块
文件定位
模块标识不含文件扩展名,按照 .js,.json,.node 的优先级补充扩展名,该过程是阻塞式的引入,因此 .json, .node 文件带上扩展名,可以加快加载速度
若模块标识不是文件名,查找当前目录下的 package.json 文件,把 main 属性的值作为文件路径进行定位
若当前目录下不存在 package.json 文件,把模块标识当成一个目录名称,将 index 作为模块默认文件名,找不到模块会抛出查找失败错误
编译执行
- 新建模块对象,模块对象的定义如下
function Module(id, parent) { |
根据路径载入文件并编译,不同文件的载入方式不同
.js 文件通过 fs 模块同步读取后编译
.node 文件通过 dlopen 方法加载编译后的二进制文件
.json 文件,通过 fs 模块同步读取后,使用 JSON.parse 解析返回结果
其他都按 .js 文件载入
编译成功的文件模块,以文件路径为索引,缓存到 Module._cache 对象上,核心模块缓存到 NativeModule._cache对象上
参考文献:
深入浅出 nodeJs
本文标题:nodeJs 模块机制
文章作者:Canace
发布时间:2021-06-28
最后更新:2023-05-26
原始链接:https://canace.site/nodeJs%E6%A8%A1%E5%9D%97%E6%9C%BA%E5%88%B6/
版权声明:转载请注明出处
分享