大多数人都知道 Node.JS 中 require() 函数做什么的, 但是有多少人知道它的工作原理呢? 我们每天使用它加载库包和模块, 但是它的内部行为原理很神秘.
我们追寻 Node 模块系统的核心: module.JS, 这个文件包含一个令人惊讶的神奇功能, 它负责加载 编译和缓存每个用过的文件, 让我们揭开它的神秘面纱.
- function Module(id, parent) {
- this.id = id;
- this.exports = {};
- this.parent = parent;
- // ...
在 module.JS 中可以发现这个 Module 类型, 扮演两个主要角色: 首先, 它提供一个所有 Node.JS 模块从其文件被加载时构建一个实例的基础功能, 甚至在文件运行时持久, 这就是为什么我们能够将一些属性加入 module.exports, 并在需要时返回它们.
module 的第二个事情是处理 Node 模块的加载机制, 标准的 require 函数其实是基于 module.require 的抽象, 后者只是一个对 Module._load 的简单包装, 加载方法处理每个文件的实际加载. 看看它的代码大概如下:
- Module._load = function(request, parent, isMain) {
- // 1. 在 Module._cache 中检查模块是否被缓存
- // 2. 如果缓存中为空, 创建一个新的模块实例.
- // 3. 保存到缓存
- // 4. 使用指定的名称调用 module.load()
- // 在读取了文件内容后将调用 module.compile()
- // 5. 如果加载和分析文件时有错误
- // 从缓存中删除坏的模块
- // 6. 返回 module.exports
- };
Module._load 负责加载新的模块并且管理模块缓存, 缓存每个模块能够降低文件的读取频率, 从而提高性能, 共享模块实例允许像单例模块那样跨应用保存状态.
如果一个模块在缓存中不存在, Module._load 将读取文件创建一个新的, 读取文件内容成功后会调用 module._compile
如果你注意上面第六步, 你会看到返回的是 module.exports, 这就是为什么当你定义公共接口时, 可以使用 exports 和 module.exports, 因为它们确实是 Model._load 和 require 返回的.
下面看看 module._compile:
- Module.prototype._compile = function(content, filename) {
- // 1. 创建调用模块需要的 require 标准函数
- // 2. 将其他帮助方法加入 require.
- // 3. 包装 JS 代码到一个函数, 这个函数提供我们的 require
- // 模块, 比如变量本地化到模块的作用域
- // 4. 返回这个函数
- };
这里有魔术发生, 首先, 一个特殊的标准 require 函数将被创建, 这就是我们熟悉的 require() 函数, 当函数自己包装了 Module.require, 它还包含一些很少人知道的帮助属性和方法, 如:
require(): 加载一个外部模块
require.resolve(): 根据其绝对路径解决模块名称
require.main: 主要的模块
require.cache: 所有缓存模块
require.extensions: 基于文件的扩展名可用于编译的方法.
一旦 require 准备就绪, 整个源码将被包装进一个新的函数, 这个函数有 require module 和 exports 和其他暴露变量作为参数, 这创建了模块的一个新函数作用域, 这样就不会污染 Node.JS 环境的其余部分.
- (function (exports, require, module, __filename, __dirname) {
- // YOUR CODE INJECTED HERE! 你的代码在这里
- });
最后, 这个包装了模块的函数将运行, 整个 Module._compile 方法同步执行, 这样原来对 Module._load 方法调用将会等待这个代码运行, 然后才会完成, 返回 module.exports 给用户.
现在, 我们已经知道 require('模块') 是如何通过模块系统加载你定义的模块的, module.JS source code 包含更多代码原理, 如果你有兴趣可以发现更多.
更多 web 前端开发 https://www.html.cn/ 知识, 请查阅 HTML 中文网 !!
来源: http://www.css88.com/web/node-js/17722.html