脚手架难点(2)-require源码解析

920 阅读2分钟

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就是主模块