1. CommonJS模块规范

1.1 模块引用

var math = require('math');

1.2 模块定义

  • exports.some就是给这个对象上添加属性
  • 直接使用 module.exports = {...} 则可以让外部直接获取到这个对象,相当与为exports换了一个引用,如果在这之前使用exports.some会把之前的覆盖

1.3 CommonJS 用法

// a.js
module.exports = {
a: 1
}
// or
exports.a = 1 // b.js
var module = require('./a.js')
module.a // -> log 1

1.4 原理

var module = require('./a.js')
module.a
// 这里其实就是包装了一层立即执行函数,这样就不会污染全局变量了,
// 重要的是 module 这里,module 是 Node 独有的一个变量
module.exports = {
a: 1
}
// module 基本实现
var module = {
id: 'xxxx', // 我总得知道怎么去找到他吧
exports: {} // exports 就是个空对象
}
// 这个是为什么 exports 和 module.exports 用法相似的原因
var exports = module.exports
var load = function (module) {
// 导出的东西
var a = 1
module.exports = a
return module.exports
};
// 然后当我 require 的时候去找到独特的
// id,然后将要使用的东西用立即执行函数包装下,over

2. Node的模块实现

在Node中引入模块,需要经历3个步骤

  • 路径分析
  • 文件定位
  • 编译执行
  • 核心模块在编译中编译成了二进制文件。在Node进程启动时,部分核心模块就被直接加载入内存。所以这部分核心模块引入时就省了文件定位和编译执行这两个步骤,并且在路径分析中优先判断,它的加载速度是最快的。

  • 文件模块是运行时动态加载。需要完整的路径分析、文件定位、编译执行

2.1 优先从缓存加载

不管是核心模块还是文件模块,require()都一律采用缓存优先的方式。

2.2 路径分析和文件定位

2.2.1 模块标识符分析

  • 核心模块
  • 路径形式的文件模块
  • 自定义模块
    • node_modules下
    • 查找最费时

2.2.2 文件定位

  • 文件拓展名分析

    • 如果省略拓展名,回按 .js .node .json的次序依次尝试
    • 如果.node .json的话,加上拓展名会加快一点速度
    • 同步配合缓存,可大幅缓解单线程中阻塞式调用的缺陷
  • 目录分析和包
    • 如果没有文件名,会将Index当作默认文件名

2.3 模块编译

  • .js文件

    • 通过fs同步读取后编译执行
  • .node
    • 这是用C/C++编写的拓展文件,通过dlopen()方法加载最后编译生成的文件
  • .json
    • 用JSON.parse()解析返回结果
  • 其余拓展名
    • 当作.js文件处理

2.3.1 js模块的编译

(funciton(exports, require, module, __filename, __dirname) {

  /* 自己写的代码  */

});
exports = function() {
// my class
} var change = function(a) {
a = 100;
} var a = 10;
change(a);
console.log(a); // => 10

如果要达到require引入一个类的效果,请赋值给 module.exports对象。这个迂回的方案不改变形参的引用。

2.3.2 C/C++ 模块的编译

Node调用process.dlopen()方法进行加载和执行。

实际上 .node模块并不需要编译,因为它是编写C/C++模块之后编译生成的,所以这里只有加载和执行的过程。在执行的过程中,模块exports对象与.node模块产生练习,然后返回给调用者。

3. 核心模块

  1. C/C++拓展模块

  2. 模块调用栈

  3. 前后端公用模块

  4. 模块侧重点

  • 前端瓶颈在于带宽,后端瓶颈在于CPU和内存等资源。前端需要通过网络加载代码,后端则从磁盘加载,二者加载速度不再同一量级上。

  • node的模块引入几乎都是同步的,但前端模块若是也采用同步方式来引入必会在用户体验上造成很大的问题,即UI初始化实际过长

4. AMD规范

定义如下

define(id?, dependencies, factory);

5. CMD 规范

CMD支持动态引入

define(funtion(require, exports, moudle) {
// The module code goes here
})
05-02 18:30
查看更多