require的加载规则:
在Node.js中,使用require
函数加载模块。Node.js会按照以下规则来查找和加载模块:
- 如果传入的是一个核心模块(例如
fs
、http
等),则直接返回核心模块的导出对象。 - 如果传入的是以
./
或../
或/
开头的相对或绝对路径,则按照路径加载模块。
- 先将路径转化为真实的文件路径。
- 然后将这个文件路径作为一个模块的标识符,根据该标识符查找模块。
- 如果传入的是一个非核心模块的名称(例如
express
、lodash
等),则按照以下步骤查找并加载模块:
- 首先,在当前目录的
node_modules
子目录中查找是否有该模块。 - 如果当前目录没有该模块,则继续在父目录的
node_modules
子目录中查找,直到找到该模块或者到根目录为止。 - 如果在以上步骤中没有找到该模块,则会查找全局安装的模块(使用
npm install -g
安装的模块)。
- 如果以上步骤都没有找到该模块,则会抛出一个
Error
。
需要注意的是,加载模块时,Node.js会缓存已经加载的模块,下次再次加载同一个模块时,会直接从缓存中读取,而不会再次加载该模块。这也是为什么在Node.js中,可以在多个文件中使用同一个模块,而不必担心该模块被加载多次的问题。
如果非路径形式的标识
路径形式的标识:
./ 当前目录 不可省略 ../ 上一级目录 不可省略 /xxx也就是D:/xxx 带有绝对路径几乎不用(D:/a/foo.js)
首位表示的是当前文件模块所属磁盘根目录
require('./a');
核心模块
核心模块本质也是文件,核心模块文件已经被编译到了二进制文件中了,我们只需要按照名字来加载就可以了require('fs');
第三方模块
凡是第三方模块都必须通过npm下载(npm i node_modules),使用的时候就可以通过require('包名')来加载才可以使用
第三方包的名字不可能和核心模块的名字是一样的.
既不是核心模块,也不是路径形式的模块
先找到当前文所述目录的node_modules 然后找node_modules/art-template目录 node_modules/art-template/package.json node_modules/art-template/package.json中的main属性 main属性记录了art-template的入口模块 然后加载使用这个第三方包 实际上最终加载的还是文件 如果package.json不存在或者mian指定的入口模块不存在 则node会自动找该目录下的index.js 也就是说index.js是一个备选项,如果main没有指定,则加载index.js文件 如果条件都不满足则会进入上一级目录进行查找
注意:一个项目只有一个node_modules,放在项目根目录中,子目录可以直接调用根目录的文件var template = require('art-template');
模块标识符中的/
和文件操作路径中的/
文件操作路径:
// 咱们所使用的所有文件操作的API都是异步的 // 就像ajax请求一样 // 读取文件 // 文件操作中 ./ 相当于当前模块所处磁盘根目录 // ./index.txt 相对于当前目录 // /index.txt 相对于当前目录 // /index.txt 绝对路径,当前文件模块所处根目录 // d:express/index.txt 绝对路径 fs.readFile('./index.txt',function(err,data){ if(err){ return console.log('读取失败'); } console.log(data.toString()); })
模块操作路径:
// 在模块加载中,相对路径中的./不能省略 // 这里省略了.也是磁盘根目录 require('./index')('hello')
总结和思考
Node.js 中的模块是通过 require() 函数来加载的,require() 函数接受一个字符串参数,指定需要加载的模块名称。Node.js 会根据模块名称从文件系统中寻找对应的模块文件并进行加载。
Node.js 中的模块分为两类,一类是核心模块,另一类是用户自定义模块。
核心模块是指 Node.js 中内置的模块,如 fs、http、path 等,它们可以直接通过 require() 函数来加载,无需指定模块路径。Node.js 将核心模块打包到了二进制文件中,因此加载速度很快。
用户自定义模块是指用户自己编写的模块,它们可以通过文件系统中的路径来加载。Node.js 会根据 require() 函数传入的模块名来搜索模块文件,具体搜索路径如下:
- 如果模块名称是以相对路径(./ 或 ../)开头的,Node.js 会以当前文件所在目录为根目录,计算出模块文件的绝对路径,并加载该模块文件。
- 如果模块名称是以绝对路径(/)开头的,Node.js 会以文件系统根目录(通常是 /)为根目录,计算出模块文件的绝对路径,并加载该模块文件。
- 如果模块名称不是以相对路径或绝对路径开头的,Node.js 会从当前模块的 node_modules 目录下开始查找该模块文件,具体查找方式如下:
- Node.js 首先在当前模块的 node_modules 目录下查找该模块文件,如果找到则直接加载该模块文件。
- 如果当前模块的 node_modules 目录下没有找到该模块文件,则 Node.js 会继续在当前模块的父级目录的 node_modules 目录下查找,直到找到该模块文件或者到达文件系统的根目录为止。
如果以上步骤都没有找到该模块文件,则 require() 函数会抛出一个 Error 异常。
总的来说,Node.js 中的 require() 函数通过模块名称来加载模块,具体的加载路径是根据模块名称的类型和当前模块所在的位置来计算的。了解 require() 函数的加载规则对于 Node.js 的模块加载机制有着重要的意义。