最近在学习 webpack源码,由于源码比较复杂,就先梳理了一下整体流程,就参考官网的例子,手写一个最基本的 webpack 模块解析器。
代码很少,github地址:手写webpack模块解析器
整体流程分析
1、读取入口文件。
2、将内容转换成 ast 语法树。
3、深度遍历语法树,找到所有的依赖,并加入到一个数组中。
4、将 ast 代码转换回可执行的 js 代码。
5、编写 require 函数,根据入口文件,自动执行完所有的依赖。
6、输出运行结果。
createAsset
// 读取内容并提取它的依赖关系
function createAsset(filename) {
// 以字符串的形式读取文件
const content = fs.readFileSync(filename, "utf-8");
// 转换字符串为ast抽象语法树
const ast = babylon.parse(content, {
sourceType: "module"
});
const dependencies = [];
// 遍历抽象语法树
traverse(ast, {
// 每当遍历到import语法的时候
ImportDeclaration: ({ node }) => {
// 把依赖的模块加入到数组中
dependencies.push(node.source.value);
}
});
const id = ID++;
// 转换为浏览器可运行的代码
const { code } = babel.transformFromAstSync(ast, null, {
presets: ["@babel/preset-env"]
});
return {
id,
filename,
dependencies,
code
};
}
createGraph
// 从入口开始,分析所有依赖项,形成依赖图,采用深度优先遍历
function createGraph(entry) {
const mainAsset = createAsset(entry);
// 定义一个保存依赖项的数组
const queue = [mainAsset];
for (const asset of queue) {
const dirname = path.dirname(asset.filename);
// 定义一个保存子依赖项的属性
asset.mapping = {};
asset.dependencies.forEach(relativePath => {
const absolutePath = path.join(dirname, relativePath);
const child = createAsset(absolutePath);
// 给子依赖项赋值
asset.mapping[relativePath] = child.id;
// 将子依赖也加入队列中,循环处理
queue.push(child);
});
}
return queue;
}
bundle
// 根据生成的依赖关系图,生成浏览器可执行文件
function bundle(graph) {
let modules = "";
// 把每个模块中的代码放在一个function作用域内
graph.forEach(mod => {
modules += `${mod.id}:[
function (require, module, exports){
${mod.code}
},
${JSON.stringify(mod.mapping)},
],`;
});
// require, module, exports 不能直接在浏览器中使用,这里模拟了模块加载,执行,导出操作。
const result = `
(function(modules){
// 创建一个require()函数: 它接受一个 模块ID 并在我们之前构建的模块对象查找它.
function require(id){
const [fn, mapping] = modules[id];
function localRequire(relativePath){
// 根据mapping的路径,找到对应的模块id
return require(mapping[relativePath]);
}
const module = {exports:{}};
// 执行转换后的代码,并输出内容。
fn(localRequire,module,module.exports);
return module.exports;
}
// 执行入口文件
require(0);
})({${modules}})
`;
return result;
}
执行解析
const graph = createGraph("./entry.js");
const result = bundle(graph);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
标签:
webpack模块解析器
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件!
如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
暂无“如何实现一个webpack模块解析器”评论...
更新动态
2025年11月07日
2025年11月07日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]