Node require方法加载规则

优先从缓存加载

有3个js文件,main.js,a.js,b.js

main.js

require('./a')
require('./b')

a.js

console.log('a.js被加载了')
require('./b')

b.js

console.log('b.js被加载了')

当在node中执行main.js时,打印结果为'a.js被加载了' 'b.js被加载了'各打印一次

首先加载a.js,打印一次'a.js被加载了'。在a.js中又加载b.js,打印一次'b.js被加载了',然后回到main.js中,执行require('./b.js'),由于在a.js中已经加载过b.js了,优先从缓存中加载,所以这里不会重复加载,并不会再打印一次'b.js被加载了'。

main.js中的require('./b')只是为了 得到其中的接口对象 ,并不会重复执行里面的代码。

main.js

require('./a')
const fn = require('./b')

console.log(fn)

a.js

console.log('a.js被加载了')
const fn = require('./b')

console.log(fn)

b.js

console.log('b.js被加载了')

module.exports = function () {
    console.log('b的方法')
}

执行main.js,打印结果为

a.js被加载了
b.js被加载了
[Function]
[Function]

这样做的目的是为了避免重复加载,提高模块加载效率 

判断模块标识

共有三种模块

  • 核心模块
  • 第三方模块
  • 自己写的模块

路径形式的模块(自己写的模块)

一般以

    ./ (当前目录,不可省略)

    ../ (上一级目录,也不可省略) 

     开头,首位的  /  表示的是当前文件模块所属磁盘的根路径,在MAC等不区分磁盘系统中表示根目录,这种方式几乎不用 

    或者绝对路径(几乎不用)

.js后缀名可以省略 

非路径形式1(核心模块)

核心模块的本质也是文件,已经被编译至二进制中,我们只需要按照名字来加载即可。在github中搜索nodejs可以看到源码,核心模块代码都在lib文件夹中,其中有http.js,path.js等

非路径形式2(第三方模块)

以art-template模块为例

首先在目录中npm i art-template

通过require('包名')即可使用

require('art-template')

不可能有任何一个第三方包与核心模块的名字是一样的,这些包是不允许提交的

第三方包的查找机制

  1. 先找到当前文件所属目录中的node_modules目录
  2. node_modules/art-template
  3. node_modules/art-template/package.json
  4. node_modules/art-template/package.json中的main属性
  5. main属性中记录了第三方包的入口模块
  6. 之后加载使用第三方包
  7. 如果package.json不存在或者其中的main属性指向的文件不存在,则node会自动找当前目录的index.js。也就是index.js会作为一个默认备选项
  8. 如果以上任何一个条件都不成立,则会进入上一层的node_modules目录查找
  9. 如果上一层还没有,会继续向上查找,一直找到根目录。
  10. 如果都没有找到,会报错 can not find module xxx
原文地址:https://www.cnblogs.com/lianglanlan/p/12534026.html