跳到主要内容

模块加载器

如何实现⼀个模块加载器?请描述其基本原理。

// commonjs模块
var moduleCache = {};
var moduleRegistry = {};

function require(moduleName) {
if (moduleCache[moduleName]) {
return moduleCache[moduleName].exports;
}
var module = moduleCache[moduleName] = {
exports: {},
loaded: false
};
moduleRegistry[moduleName] = function() {
module.loaded = true;
module.exports = module.exports || {};
module.exports.__esModule = true;
module.exports.default = module.exports;
module.exports.__useDefault = true;
};
loadScript('path/to/' + moduleName + '.js', function() {
moduleRegistry[moduleName]();
});
return module.exports;
}

function loadScript(src, callback) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
script.onload = function() {
callback();
};
document.head.appendChild(script);
}

// 使用模块
require('moduleA').publicMethod();


// 模拟模块加载器
function ModuleLoader() {
this.modules = {};
}
ModuleLoader.prototype.load = function (path) {
if (this.modules[path]) {
return Promise.resolve(this.modules[path]);
}
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf8', (err, data) => {
if (err) {
reject(err);
return;
}
const module = this.parseModule(data);
const result = this.executeModule(module);
this.modules[path] = result;
resolve(result);
});
});
};

ModuleLoader.prototype.parseModule = function (source) {
// 这里可以使用正则表达式或解析器来解析模块代码
// 例如,提取出所有的import和export语句
// 为了简化,我们假设模块只导出一个值
const exports = {};
const exportStatement = 'export default value;';
const match = source.match(/value\s*=\s*(\S+)/);
if (match) {
exports.default = match[1];
}
return exports;
};

ModuleLoader.prototype.executeModule = function (module) {
// 这里可以使用eval或new Function来执行模块代码
// 为了简化,我们直接返回模块的导出值
return module;
};

// 使用模块加载器
const loader = new ModuleLoader();
loader.load('./module.js').then(module => {
console.log(module); // 输出模块导出的值
});