一、nodejs模块机制简介
nodejs是ECMAScript的一个里程碑式的突破。nodejs出现之前,ECMAScript只能运行在浏览器上,与浏览器内部实现的的Dom和Bom,一起为前端页面提供动态行为机制,成为前端的附庸。nodejs出现后,javascript有了自己的编译和执行环境,统一了前后端。在nodejs中,模块机制的实现,使其开发大型应用成为了可能。nodejs中的模块机制是对CommomJS规范中模块规范的实现,nodejs的模块机制主要包含三个标识:模块引用标识(require)、模块导出标识(exports)、模块标识(传递给require的参数)。
二、模块定义标识(exports)
一个*.js文件就是一个模块,而模块内的变量、函数、类等都可以导出。在模块内部,有一个全局变量module,module是nodejs为每个提供提供的一个全局变量,module有一个exports属性,我们导入模块时,实际上导入的就是module.exports这个对象。所以如果想导出模块内的成员,可以给module.exports添加属性。没有被添加的,就只能在模块内使用。
比较一下截图中的math对象和module.exports对象的输出结果,就知道如何导出和导入了。后面就不再介绍如何使用require了,也可以使用解构module.exports来获取制定的导入对象。
三、模块标识(传递给require的参数)
传递给require的参数可以分为四类:
- 核心模块
const fs = require("fs");
- 相对路径形式的本地模块
const fs = require("./index.js");
- 绝对路径形式的本地模块
const fs = require("/home/will/nodejsPro/nodejs-module-test/index.js");
- 模块名形式的本地模块
const fs = require("math");
前三种不言而喻,今天主要记录一下第四种模块名形式的本地模块的搜索机制。
四、模块名形式的本地模块的模块搜索机制
还记得我们module对象的输出结果吗?其中module.paths就是我们搜索机制的核心了。nodejs会按照module.path里面的路径一级一级往上找,在某一级node_modules中找到对用的模块包后,就会读取包中的package.json文件,找到main属性指定的文件名,如果main属性名指定的文件名错误获取没有package.json文件,就会默认index为文件名,然后导入index文件内部的module.exports对象。(实际上没有这么简单,只是为了方便理解,简单记录一下)
Module {
id: '.',
path: '/home/will/byteDancePro/ts-test',
exports: {},
filename: '/home/will/byteDancePro/ts-test/index.js',
loaded: false,
children: [],
paths: [
'/home/will/byteDancePro/ts-test/node_modules',
'/home/will/byteDancePro/node_modules',
'/home/will/node_modules',
'/home/node_modules',
'/node_modules'
]
}