Node模块加载导出机制
2019-05-17 本文已影响1人
xdoer
Node中的每一个文件模块都是对象。根据require中传入文件名或者地址,查找缓存,内置模块,找不到时,会创建一个包含filename属性的Module实例。根据判断文件后缀为js时,调用函数找到并读取文件,调用编译函数。我们编写的模块在编译函数的示例代码中的compiledWrapper中执行.
function Module(id, parent) {
this.id = id;
this.exports = {};
this.parent = parent;
if (parent && parent.children) {
parent.children.push(this);
}
this.filename = null;
this.loaded = false;
this.children = [];
}
//导出当前模块
module.exports = Module;
//require方法,用于获取需要的文件
Module.prototype.require = function(path) {
return Module._load(path, this);
};
//加载需要的文件
Module.prototype.load = function(filename) {
//判断文件扩展名
var extension = path.extname(filename) || '.js';
if (!Module._extensions[extension]) extension = '.js';
//调用处理函数
Module._extensions[extension](this, filename);
this.loaded = true;
};
//扩展名为js的文件处理
Module._extensions['.js'] = function(module, filename) {
var content = fs.readFileSync(filename, 'utf8');
module._compile(stripBOM(content), filename);
};
//编译
Module.prototype._compile = function(content, filename) {
//这里的this指的是在Module_.load中创建的包含filename和loaded的Module对象实例module
var self = this;
//这里要注意这几个参数
//self.exports是空对象
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);
};
Module._load = function(request, parent, isMain) {
// 计算绝对路径
var filename = Module._resolveFilename(request, parent);
// 如果有缓存,取出缓存
var cachedModule = Module._cache[filename];
if (cachedModule) {
return cachedModule.exports;
// 是否为内置模块
if (NativeModule.exists(filename)) {
return NativeModule.require(filename);
}
// 生成模块实例,存入缓存
var module = new Module(filename, parent);
Module._cache[filename] = module;
// 加载模块
try {
module.load(filename);
hadException = false;
} finally {
if (hadException) {
delete Module._cache[filename];
}
}
// 输出模块的exports属性
return module.exports;
};
var compiledWrapper = function(exports,require,module,_filename,_dirname){
---------------------------------------
//我们编写的模块
var math = require('mvc.html');
//require返回模块的exports属性,可使用上面挂载的函数属性
exports.area = function(){
return math.PI*3*3;
}
---------------------------------------
}
参考:
1、阮一峰《require()源码解读》
http://www.ruanyifeng.com/blog/2015/05
/require.html#comment-349814
2、朴灵《深入浅出NodeJS》