require源码流程图
require主流程
相对路径引入的模块
1.先找到require(key) key的绝对路径和id 去loadnativemodule找是否是内置模块 是的话直接返回内置模块的exports
2.如果不是内置模块 就会new module(key)创建一个module对象
3.进入module.load方法
4.进入后首先拿到文件后缀 调用内部指定的对应后缀的function
js->readfile拿到js源码字符串—>去掉bom头(在utf-8编码文件中BOM在文件头部,占用三个字节,用来标示该文件属于utf-8编码,现在已经有很多软件识别bom头,但是还有些不能识别bom头)->调用module.compile
5.module.compile
先判断是否用# !开头 是的话就是脚手架 一般不是
后给我们源码套一个立即执行函数的壳 传入require,exports,module,__filename,__dirname这五个变量
递归执行每个文件的require
内置模块
2.如果是内置模块
3.拿到对应模块的module对象的exports返回
Node_mdoules模块
2.如果是node_modules模块
3.(通过resolveFilename函数找到模块的真实路径)解析路径的时候会解析到node_modules下(解析相对路径能拿到绝对路径) 后面一样的
所以关键是resolveFilename函数
resolveFilename会调用_resolveLookupPaths函数 从 最上面的node_modules找 如果不是
则是相对路径 直接dirnamep拼接
.json/node文件怎么加载
json->utf8格式拿到文件字符串后去掉bom头 然后JSOn.parse即可
node->调用dlopen去加载c++插件
缓存机制
如果连续require('fs)
const a = require('fs')
const b =require('fs')
a其实就是b 因为内部做了缓存 找到缓存了的就直接返回exports 不去执行后续逻辑了
缓存(key:绝对路径>value:module对象)
CommonJs加载主模块流程
1.cjs.runmain
2.module._load(传入['node','index.js']的第二个参数 即index.js 当module的key)
3.module.load和require后面一样了
node index.js 则index.js就是主模块