当在Node.js中调用require()方法时,Node.js会按照一定的加载规则进行模块的加载。本文将详细讲解Node.js中require()方法的加载规则。
基本概念
-
在讲解require()方法的加载规则之前,需要先说明以下几个概念:
-
模块:在Node.js中,每个文件都被看作一个模块,模块可以导出(export)和导入(import)。当代码需要使用某个模块时,可以使用require()方法来导入该模块。
-
模块标识符:在调用require()方法时,需要传入一个模块标识符。模块标识符是指模块的名称,可以是相对路径或者绝对路径。
加载规则
Node.js中require()方法的加载规则如下:
- 如果模块标识符是一个核心模块(built-in module),即Node.js自带的模块,如fs、http等,直接返回该模块的导出对象。
- 如果模块标识符以/、.\或…/开头,则按照路径加载该模块,加载顺序为:
- 检查模块文件是否存在。
- 如果存在,则加载该模块文件并缓存。
- 如果不存在,则检查该模块是否有扩展名称,如.js、.json、.node等。
- 如果有扩展名称,则按照该扩展名称的规则查找文件并加载。
- 如果没有扩展名称,则按照.js、.json、.node的顺序尝试查找文件并加载。
- 如果找不到对应文件,则抛出MODULE_NOT_FOUND错误。
例如,在当前模块目录下存在foo.js文件,即./foo.js。则可以通过以下方式加载该模块:const foo = require(‘./foo’)。
如果存在foo.json文件,则可以通过以下方式加载该模块:const foo = require(‘./foo.json’)。
- 如果模块标识符不是以/、.\或…/开头,则按照以下规则从父级目录开始查找模块。
-
在当前目录下查找node_modules目录。
-
如果在当前目录下找到了node_modules目录,则按照以下规则查找对应模块。
-
- 如果存在node_modules/模块标识符.js文件,则加载该文件并返回。
如果存在node_modules/模块标识符/index.js文件,则加载该文件并返回。
如果存在node_modules/模块标识符/package.json文件,并且该文件中有指定main属性,则加载package.json中指定的目标文件。
如果存在node_modules/模块标识符/index.node文件,则加载该文件并返回。
如果找不到对应的模块,则继续在上一级目录中查找node_modules目录,直到找到为止。
- 如果存在node_modules/模块标识符.js文件,则加载该文件并返回。
-
如果在父级目录中找不到node_modules目录,则继续向上查找,直到根目录为止。
如果在所有目录中都找不到对应的模块,则抛出MODULE_NOT_FOUND错误。
例如,有如下目录结构:
project
├── node_modules
│ ├── foo.js
│ └── bar
│ └── index.js
├── index.js
└── package.json
在index.js中通过以下方式可以加载到foo模块:const foo = require(‘foo’)。
在bar.js中通过以下方式可以加载到index.js模块:const index = require(‘bar’)。
示例
- 加载非核心模块
假设有如下目录结构:
project
├── index.js
└── foo
└── index.js
project/foo/index.js中的代码如下:
javascript
module.exports = ‘foo module’;
project/index.js中的代码如下:
javascript
const foo = require(‘./foo’);
console.log(foo); // 输出:foo module
该示例演示了如何使用相对路径加载非核心模块。
- 加载使用了扩展名的模块
假设有如下目录结构:
project
├── index.js
└── foo.js
project/foo.js中的代码如下:
javascript
module.exports = ‘foo module’;
project/index.js中的代码如下:
javascript
const foo = require(‘./foo.js’);
console.log(foo); // 输出:foo module
该示例演示了如何通过带有扩展名的路径来加载模块。
总结
本文介绍了Node.js中require()方法的加载规则。在使用require()方法加载模块时,需要根据模块标识符的前缀来确定加载路径,同时还需要注意模块是否存在、扩展名的处理及循环依赖的问题。
转载自:https://pythonjishu.com/smrhikbzkvjeojz/