CommonJS modules in Node.js
Introduction
最初的 JavaScript 设计时没有模块化相关的概念,但是随着前端的发展及其工程化的引进和借鉴,相关的模块化思想也被引入了前端领域,其中CommonJS
的模块化解决方案一直屹立不倒。为了更好的理解CommonJS
,本篇文章依据Module:CommonJS modules相关文档,借鉴loader.js的相关源码,自己手动实现一个CommonJS module
;
The Module Wrapper
每个被 require 的模块,在执行之前都被一个函数包裹,类似于:
1 | (function (exports, require, module, __filename, __dirname) { |
这样做可以防止模块内的定义的变量提升到全局作用域,同时提供了module
,exports
等变量供当前模块使用
What require()
does:
require()
加载模块的顺序具体可以参考这段伪代码,简单概括如下:
- 优先加载诸如
path
,fs
等核心模块 - 先从缓存中找对应的模块是否已加载,没有则进行下一步
- 加载对应的以
/
,./
,../
开头的文件,如果不带文件后缀,则按照.js
,.json
,.node
依次尝试,有的话加载对应的文件内容 - 加载对应的以
/
,./
,../
开头的文件夹,先查找文件夹下的package.json
,如果package.json
定义了”main”,则加载”main”对应的内容,没有则寻找对应的文件夹下的 index 文件,然后按照第三步的加载文件顺序依次查找并加载 - 加载对应的
node_modules
文件夹下的内容 - 抛出”not found”错误
对于最新版本的Node.js
则增加了ECMAScript modules相关的加载规则,有兴趣的可以了解一下。