CommonJS modules in Node.js

Introduction

最初的 JavaScript 设计时没有模块化相关的概念,但是随着前端的发展及其工程化的引进和借鉴,相关的模块化思想也被引入了前端领域,其中CommonJS的模块化解决方案一直屹立不倒。为了更好的理解CommonJS,本篇文章依据Module:CommonJS modules相关文档,借鉴loader.js的相关源码,自己手动实现一个CommonJS module;

The Module Wrapper

每个被 require 的模块,在执行之前都被一个函数包裹,类似于:

1
2
3
(function (exports, require, module, __filename, __dirname) {
//Module code actually lives in here
});

这样做可以防止模块内的定义的变量提升到全局作用域,同时提供了moduleexports等变量供当前模块使用

What require() does:

require()加载模块的顺序具体可以参考这段伪代码,简单概括如下:

  1. 优先加载诸如path,fs等核心模块
  2. 先从缓存中找对应的模块是否已加载,没有则进行下一步
  3. 加载对应的以/, ./, ../开头的文件,如果不带文件后缀,则按照.js, .json,.node依次尝试,有的话加载对应的文件内容
  4. 加载对应的以/, ./, ../开头的文件夹,先查找文件夹下的package.json,如果package.json定义了”main”,则加载”main”对应的内容,没有则寻找对应的文件夹下的 index 文件,然后按照第三步的加载文件顺序依次查找并加载
  5. 加载对应的node_modules文件夹下的内容
  6. 抛出”not found”错误

对于最新版本的Node.js则增加了ECMAScript modules相关的加载规则,有兴趣的可以了解一下。

Read more