《深入浅出Node.js》- 第二章

362 阅读3分钟

一. CommonJS规范

1.1 CommonJS的出发点

CommonJS规范的提出,主要是为了弥补当前JavaScript没有标准的缺陷(如模块、二进制、Buffer等等),以达到具备开发大型应用的基础能力。

image.png

1.2 CommonJS的模块规范

CommonJS对模块的定义主要分为:模块定义、模块引用、模块标识。
在Node中,一个文件就是一个模块。

1.2.1 模块定义

模块上下文提供了module对象和exports对象。module对象代表模块自身,exportsmodule的属性;exports对象作为模块导出的唯一出口。
exports.say = function () {
    console.log('Hello Node.js!')
}

1.2.2 模块引用

模块上下文提供了require()方法来引入模块,它接受一个模块标识。
const fs = require('fs')

1.2.3 模块标识

模块标识就是传递给require()方法的参数,有以下3种类型:
    1. 小驼峰模块名称
    2. 相对路径
    3. 绝对路径

二. Node的模块实现

Node引入模块的3个步骤:
    1. 路径分析
    2. 文件定位
    3. 编译执行

Node的模块类型:
    1. 核心模块(系统模块):省略了文件定位、编译执行的步骤,并且在路径分析中优先判断,加载速度快。
    2. 文件模块(自定义模块、第三方模块):运行时动态加载,需要完整的引入模块步骤,加载速度慢。

2.1 优先从缓存加载

Node会缓存加载过的模块,核心模块的缓存检查优先与文件模块。

2.2 路径分析和文件定位

2.2.1 模块标识符分析

在Node的实现中,模块标识符分为以下几类:
    1. 核心模块,如fs、path
    2. 相对路径的文件模块
    3. 绝对路径的文件模块
    4. 非路径形式的文件模块(如axios),基于模块路径module.paths遍历查找

2.2.2 文件定位

文件扩展名分析
    在分析模块标识符的过程中,会出现标识符不包含文件扩展名的情况,Node会按.js.json.node的次序补充扩展名,依次尝试。
目录分析和包
    1. 如果文件扩展名分析失败,却得到一个目录。Node会在目录下查找package.json文件并通过JSON.parse()解析,对包描述对象的main属性值进行文件定位。
    2. 如果没有package.json文件或main属性值错误,Node会将index当做默认文件名,按照文件扩展名分析的次序依次查找。
    3. 如果目录分析失败,则进入下一个模块路径查找,以此循环直到模块路径遍历完,则会抛出查找失败的异常。

2.3 模块编译

Node对于不同的文件扩展名,载入方法也有所不同,具体如下:
    1. .js文件:通过fs模块同步读取后编译执行。
    2. .node文件:这是C/C++编写的扩展文件,通过dlopen()方法加载最后编译生成的文件。
    3. .json文件:通过fs模块同步读取后,用JSON.parse()解析返回结果。
    4. 其余扩展名:被当做.js文件载入
每一个编译成功的模块,会将其文件路径作为索引缓存在Module._cache对象上,以提高二次引入的性能。

三. NPM

NPM是Node的包管理器,用于管理、组织、使用第三方模块。

3.1 包结构

CommonJS规范的包目录结构如下:
- package.json:包描述文件
- bin:可执行二进制文件目录
- lib:js代码目录
- doc:文档目录
- test:单元测试用例目录

3.2 发布包

1. 编写模块
2. 初始化package.json(npm init)
3. 注册账号(npm adduser或通过npm官网注册)
4. 登录账号(npm login,使用淘宝镜像的同学记得把镜像还原,否则无法登录)
5. 上传包(npm publish folderName)
6. 查看包是否发布成功(npm info packageName)

3.3 NPM私域搭建

TODO