commonjs 规范
- 每个文件都是一种规范
- modbule.exports讲它导出
- 别人要用就require
const p = require('./a');
console.log(p);
const person = {
name: 'jaasdsa',
age: 12
}
module.exports = person;
实现require
- Module._load 加载某个模块
- Module._resolveFileName 解析文件名 解析出绝对路径
- new Module 创建一个新的模块 id,exports 最终导出结果
- tryModuleLoad 尝试加载块
// 实现 module类
// (function(exports,require,module,__dirname,__filename){
// module.exports = 'hello'
//
// })()
// return module.exports;
源码
const path = require('path');
const fs = require('fs');
const vm = require('vm');
function Module(id) {
this.id = id;
this.exports = {};
}
Module._resolveFileName = function(id) {
let absPath = path.resolve(id);
if (fs.existsSync(absPath))
return absPath;
let extenisons = Object.keys(Module.extenisons);
for (let i = 0; i < extenisons.length; i++) {
let ext = extenisons[i];
let currentPath = absPath + ext;
if (fs.existsSync(currentPath))
return currentPath;
}
throw new Error('文件不存在');
}
Module.wrapper = ['(function (exports, require, module, __dirname, __filename) {\r\n',
'\r\n})'
]
Module.extenisons = {};
Module.extenisons['.js'] = function(module) {
let script = fs.readFileSync(module.id, 'utf-8');
let content = Module.wrapper[0] + script + Module.wrapper[1];
let fn = vm.runInThisContext(content);
let __dirname = path.dirname(module.id);
fn.call(module.exports, module.exports, req, module, __dirname, module.id);
}
Module.extenisons['.json'] = function(module) {
let script = fs.readFileSync(module.id, 'utf-8');
module.exports = JSON.parse(script);
}
Module._cache = new Map();
function tryModuleLoad(module) {
let ext = path.extname(module.id);
Module.extenisons[ext](module);
}
function req(id) {
let fileName = Module._resolveFileName(id);
if (Module._cache.has(fileName))
return Module._cache.get(fileName).exports;
let module = new Module(fileName);
Module._cache.set(module.id, module);
tryModuleLoad(module);
return module.exports;
}
测试
let aa = req('./a');
console.log(aa);