分享免费的编程资源和教程

网站首页 > 技术教程 正文

require模块加载函数详解

goqiw 2024-09-14 07:00:28 技术教程 39 ℃ 0 评论

1、require 是一个函数,同时还挂载着四个属性

  • require.resolve 解析某个文件是否存在,存在就返回此文件的绝对路径,否则会报错
  • require.main 当前所在文件的模块信息
  • require.extensions 对象存放着能解析的文件类型,有 .js、.json、.node 三种类型
  • require.cache 对象存放着已经缓存的模块(一个文件绝对路径为键名,记载着这个文件的信息)

2、require 函数的参数说明

  • 只有一个参数
  • 参数类型都是字符串
  • 参数可以是:
  • 模块(原生内置fs/http/path/https等、第三方包模块express、koa等等)
  • 路径+文件基础名(./express 当前路径、../express 上级路径、/express 绝对路径)
  • 路径+文件基础名+文件扩展名(./express.js 当前路径、../express.json 上级路径、/express.node 绝对路径)

3、reqiure 调用的时候

- 如果引用的是 .js 文件
  - fs模块同步读取文件
  - 包装fs模块同步读取的内容
  - 调用 vm 的 runInThisContext 方法 将 包装字符串 解析为 javascript
  - 调用匿名函数,并传参,最后返回 module.exports 的赋值。

- 如果引用的是 .json 文件
  - 经过fs模块同步读取文件以后用 JSON.parse() 解析返回结果。

- 如果引用的是 .node 文件
  - 则经过 dlopen()方法加载最后编译生成的对象,并且返回结果。

4、require 加载规则

加载规则参考地址:

 https://www.jianshu.com/p/a309864c8357
 https://blog.csdn.net/u010476739/article/details/80925128
 https://www.cnblogs.com/zhoulixue/p/8757546.html
 http://www.javashuo.com/article/p-bywkbpzj-d.html
 https://juejin.cn/post/6844903704123211783

加载的模块类型:

 1、原生内置模块
     存在:原生内置模块缓冲区中,直接返回缓存结果,不执行原生内置模块代码
     不存在:原生内置模块缓冲区中,执行原生内置模块代码,把模块加入缓冲区,并返回执行结果
 2、路径文件模块
 
     (1)、构建文件绝对路径列表
         存在后缀名(.js | .json | .node)
             使用path.resolve("路径") 拼接一个绝对路径,推入文件绝对路径列表
         不存在后缀名
             使用 path.resolve("路径"+".js") 拼接一个绝对路径的 .js 文件,推入文件绝对路径列表
             使用 path.resolve("路径"+".json") 拼接一个绝对路径的 .json 文件,推入文件绝对路径列表
             使用 path.resolve("路径"+".node") 拼接一个绝对路径的 .node 文件,推入文件绝对路径列表
             是否存在 path.resolve("路径") 目录
                 存在
                     是否存在package.json文件
                         存在
                             是否存在main属性(若main没指定后缀名,那会使用 .js | .json | .node,按照顺序查找)
                                 存在
                                     使用path.resolve(path.jon("路径",'main属性值')) 拼接一个绝对路径的文件,推入 文件绝对路径列表
                                 不存在
                                     使用path.resolve(path.jon("路径",'index.js')) 拼接一个绝对路径的 .js 文件,推入 文件绝对路径列表
                                     使用path.resolve(path.jon("路径",'index.json')) 拼接一个绝对路径的 .json 文件,推入 文件绝对路径列表
                                     使用path.resolve(path.jon("路径",'index.node')) 拼接一个绝对路径的 .node 文件,推入 文件绝对路径列表
                         不存在
                             使用path.resolve(path.jon("路径",'index.js')) 拼接一个绝对路径的 .js 文件,推入 文件绝对路径列表
                             使用path.resolve(path.jon("路径",'index.json')) 拼接一个绝对路径的 .json 文件,推入 文件绝对路径列表
                             使用path.resolve(path.jon("路径",'index.node')) 拼接一个绝对路径的 .node 文件,推入 文件绝对路径列表
 
     (2)、遍历文件绝对路径列表 ,查看是否在require.cache['文件路径']缓冲区中
         存在
             读取缓冲区中的模块,不执行文件模块的代码,直接返回缓存的结果(require.cache['文件路径'].exports)
         不存在
             报错找不到模块


 3、第三方包模块
 
     (1)、获取模块可能存在的目录列表 module.paths 
 
     (2)、构建 文件绝对路径列表
 
         遍历 目录列表 module.paths 第一个元素
             使用(path.join(目录元素,包名+".js") 拼接一个绝对路径的 .js 文件,推入 文件绝对路径列表
             使用(path.join(目录元素,包名+".json") 拼接一个绝对路径的 .json 文件,推入 文件绝对路径列表
             使用(path.join(目录元素,包名+".node") 拼接一个绝对路径的 .node 文件,推入 文件绝对路径列表
             判断 path.join(目录元素,包名) 目录是否存
                 存在
                     判断目录下是否存在package.json文件
                         存在
                             是否存在main属性
                                 存在
                                     使用 path.jon(目录元素",包名,'main属性值')) 拼接一个绝对路径的文件,推入 文件绝对路径列表
                                 不存在
                                     使用 path.jon(目录元素",包名,'index.js')) 拼接一个绝对路径的文件,推入 文件绝对路径列表
                                     使用 path.jon(目录元素",包名,'index.json')) 拼接一个绝对路径的文件,推入 文件绝对路径列表
                                     使用 path.jon(目录元素",包名,'index.node)) 拼接一个绝对路径的文件,推入 文件绝对路径列表
                         不存在
                             继续遍历 目录列表 module.paths
                 不存在
                     继续遍历 目录列表 module.paths
 
     (3)、遍历文件绝对路径列表,查看是否在require.cache['文件路径']缓冲区中
         存在
             读取缓冲区中的模块,不执行文件模块的代码,直接返回缓存的结果(require.cache['文件路径'].exports)
         不存在
             报错找不到模块


5、require 3种文件的加载方式

 如果是.js文件,则经过fs模块同步读取文件为字符串,然后包装字符串为匿名函数字符串,然后使用vm.runInThisContext执行为JavaScript代码,最后调用传参。
 如果是.json文件,则经过fs模块同步读取文件以后用 JSON.parse() 解析返回结果
 如果是.node文件,则经过 dlopen()方法 加载最后编译生成的对象。.node 是C/C++编写的扩展文件

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表