We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
::: tip 我们先大致了解一下 require()引入一个 .js 或者 .json 文件时候,内部大致是怎么处理的。 :::
.js
.json
let name = require('./a') console.log(name)
上述代码引入 a.js 文件时候,内部大致发生的流程如下:
a.js
1、将 ./a 转化为绝对路径,并且补充后缀名(c:\Users\chenying\Desktop\code\a.js)
./a
c:\Users\chenying\Desktop\code\a.js
2、根据绝对路径判断缓存中是否存在缓存的文件,如果存在则取缓存,不存在则继续
3、创建 Module 实例 module,将绝对路径传入
Module
module
4、取得绝对路径的后缀名,根据后缀名(.js)调用对应的处理函数
5、读 .js 和 .json 文件思路大同小异,通过fs.readFileSync()读取文件内容
6、对读到的 .js 文件的内容外层包裹一个函数,并且将字符串转成函数执行
7、对读到的 .json 文件的内容,转为对象,并且赋值给module.exports
module.exports
::: tip 我们再来看下源码中对以下几个疑惑点是怎么进行处理的 :::
function Module(id) { this.id = id; this.exports = {}; // .. }
在源码中我们发现 Module 上挂载很多,但是我们真正需要接触到的分别是 id 和 exports,他们分别是绝对路径,和默认导出的空对象
id
exports
Module._extensions = Object.create(null); //创建一个对象 Module._extensions['.js'] = function(module, filename) {}; // 在对象上挂载 `.js`的处理函数 Module._extensions['.json'] = function(module, filename) {}; // 在对象上挂载 `.json`的处理函数 Module._extensions[extension](this, filename); // 根据绝对路径的后缀名,调用挂载在对象上相应的方法
用 Object.create(null) 是不想有原型上的属性
Object.create(null)
Module._extensions['.js'] = function(module, filename) { var content = fs.readFileSync(filename, 'utf8'); // 读取文件内容 module._compile(stripBOM(content), filename); // 对读取的内容包裹一层函数,并且转为函数自执行,让用户自己把想要导出的内容挂载到 `module.exports` 上面去 }; Module._extensions['.json'] = function(module, filename) { var content = fs.readFileSync(filename, 'utf8'); module.exports = JSON.parse(stripBOM(content)); // 读到的json文件直接挂载到 `module.exports` 上 };
let wrap = function(script) { return Module.wrapper[0] + script + Module.wrapper[1]; }; const wrapper = [ '(function (exports, require, module, __filename, __dirname) { ', '\n});' ]; const wrapper = Module.wrap(content); compiledWrapper = vm.runInThisContext(wrapper) compiledWrapper.call(this.exports, this.exports, require, this,filename, dirname)
::: tip 我们现在根据步骤结合node来实现一款require()加深理解 :::
let path = require('path'); let fs = require('fs'); let vm = require('vm'); function Module(id){ this.id = id; this.exports = {} } function myRequire(filePath){ let absPath = path.resolve(__dirname,filePath); // 把当前的filePath变成一个绝对路径 let module = new Module(absPath); module.load(); // 加载模块 return module.exports } let r = myRequire('./a.js'); console.log(r);
Module._extensions = {}; Module.prototype.load = function(){ let ext = path.extname(this.id); // 取出当前实例上挂载的绝对路径,获取后缀名 Module._extensions[ext](this) // 根据后缀名调用对应的处理函数 }
Module._extensions
let wrapper = [ '(function(exports,module,require,__dirname,__filename){' , '})' ] Module._extensions['.js'] = function(module){ let script = fs.readFileSync(module.id,'utf8'); //读取文件 let functStr = wrapper[0] + script + wrapper[1]; // 字符串包裹 let fn = vm.runInThisContext(functStr); //将字符串转为函数 fn.call(module.exports,module.exports,module,myRequire);//执行函数 } Module._extensions['.json']= function(module){ let script = fs.readFileSync(module.id,'utf8');//读取文件 module.exports = JSON.parse(script); // 将读取到的json挂载到 `module.exports` }
::: tip 目前已经根据源码思路来实现一款mini版require(),但是还有类似于实现缓存、自动补全后缀名等功能就不贴代码了,可以看下方的源码,欢迎star :::
点击查看源码
The text was updated successfully, but these errors were encountered:
No branches or pull requests
你不知道的require
require 内部流程
::: tip
我们先大致了解一下 require()引入一个
.js
或者.json
文件时候,内部大致是怎么处理的。:::
上述代码引入
a.js
文件时候,内部大致发生的流程如下:1、将
./a
转化为绝对路径,并且补充后缀名(c:\Users\chenying\Desktop\code\a.js
)2、根据绝对路径判断缓存中是否存在缓存的文件,如果存在则取缓存,不存在则继续
3、创建
Module
实例module
,将绝对路径传入4、取得绝对路径的后缀名,根据后缀名(
.js
)调用对应的处理函数5、读
.js
和.json
文件思路大同小异,通过fs.readFileSync()读取文件内容6、对读到的
.js
文件的内容外层包裹一个函数,并且将字符串转成函数执行7、对读到的
.json
文件的内容,转为对象,并且赋值给module.exports
::: tip
我们再来看下源码中对以下几个疑惑点是怎么进行处理的
:::
Module
类在源码中我们发现
Module
上挂载很多,但是我们真正需要接触到的分别是id
和exports
,他们分别是绝对路径,和默认导出的空对象取得绝对路径的后缀名,根据后缀名(
.js
)调用对应的处理函数用
Object.create(null)
是不想有原型上的属性通过fs对文件进行读取
对读到的 .js 文件的内容外层包裹一个函数,并且将字符串转成函数执行
mini 版require的实现
::: tip
我们现在根据步骤结合node来实现一款require()加深理解
:::
将传入的路径转为绝对路径,并且创建
module
实例,将module.exports导出取得绝对路径的后缀名,根据后缀名(.js)调用对应的处理函数
Module._extensions
上补充对应的处理函数::: tip
目前已经根据源码思路来实现一款mini版require(),但是还有类似于实现缓存、自动补全后缀名等功能就不贴代码了,可以看下方的源码,欢迎star
:::
源码
点击查看源码
The text was updated successfully, but these errors were encountered: