最近在学习 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的路径,找到对应的模块idreturn 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);

欢迎大家提issue,一起交流。

实现一个webpack模块解析器相关推荐

  1. B编码与BT种子文件分析,以及模仿json-cpp写一个B编码解析器

    B编码与BT种子文件分析,以及模仿json-cpp写一个B编码解析器 1.什么是B编码 2.B编码格式 3.种子文件结构 3.1.主文件结构 3.2.info结构 4.简单的例子了解一下种子文件和B编 ...

  2. webpack 模块打包器

    webpack的入门概念 概念 webpack是现代Javascript应用程序的模块打包器.当webpack处理程序时,它会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将这些模块打 ...

  3. webpack模块解析

    模块 在模块化编程中,开发者将程序分解成离散功能块(discrete chunks of functionality),并称之为模块 每个模块具有比完整程序更小的接触面,使得校验.调试.测试轻而易举. ...

  4. 如何实现一个Java Class解析器

    最近在写一个私人项目,名字叫做ClassAnalyzer,ClassAnalyzer的目的是能让我们对Java Class文件的设计与结构能够有一个深入的理解.主体框架与基本功能已经完成,还有一些细节 ...

  5. 【编译原理】构建一个简单的解释器(Let’s Build A Simple Interpreter. Part 7.)(笔记)解释器 interpreter 解析器 parser 抽象语法树AST

    [编译原理]让我们来构建一个简单的解释器(Let's Build A Simple Interpreter. Part 7.) 文章目录 python代码 插--后序遍历 C语言代码(有错误) C语言 ...

  6. 从零编写一个解析器(1)—— 解析数字

    文章名称:从零编写一个解析器(1)-- 解析数字 参考地址:https://github.com/Geal/nom/blob/master/doc/making_a_new_parser_from_s ...

  7. JavaScript模块打包器rollup

    学习资料:拉勾课程<大前端高薪训练营> 阅读建议:搭配文章的侧边栏目录进行食用,体验会更佳哦. 内容说明:本文不做知识点的搬运工,技术详情请查看官方文档. 一:认识rollup rollu ...

  8. Python之父发文,将重构现有核心解析器

    原题 | PEG Parsers 作者 | Guido van Rossum 译者 | 豌豆花下猫 转载自 Python猫(ID: python_cat) 导语:Guido van Rossum 是 ...

  9. java正则表达式去除xml标签之间的空格_HTML解析器——htmlparser2使用详解,换个姿势解析html和xml

    上一篇文章我们介绍了一个html/xml解析器--htmlparser,这篇文章我们介绍另外一个解析模块htmlparser2,后者是对前者的重构,同时对前者的API做了部分兼容. 用法简介 安装 c ...

最新文章

  1. 读过本文才算真正了解Cassandra数据库
  2. ALV显示红绿灯(FMnbsp;ALVnbsp;和nbsp;OOnbsp;ALV两…
  3. 【JEECG技术博文】JEECG图表配置说明
  4. html计算天数,Javascript实现简易天数计算器
  5. centOS6.6虚拟机启动后登陆界面无法显示
  6. readline_Swift readLine(),Swift print()
  7. 知识图谱特征学习算法
  8. 最好用电脑录音软件推荐
  9. vue axios的封装大全
  10. 10.【Axure 10 】菜单-文件-导入RP文件
  11. c语言字符统计程序源代码,c语言程序实例大全-220个详细程序源代码.rar
  12. 【imx6ul】从头搭建imx6ul开发环境(uboot、内核编译及烧入、mfgtools详细使用方法)
  13. 高考476分在浙江计算机学院,2021年高考476分左右能上什么大学(100所)
  14. 数学竞赛辅导陈启浩pdf_【优秀论文】第九届MathorCup高校数学建模挑战赛(B题)...
  15. INTERCEPTOR DISCONNECTED 的问题
  16. @RunWith注解找不到,怎么办?
  17. [转]淘宝的十年技术之路
  18. 一个实际电路的原理图是怎样设计出来的?
  19. Noise2Noise的一些学习总结
  20. NOJ - 2070 马尔扎哈的疑惑

热门文章

  1. JAVA中console方法怎么用_Java中Console对象实例代码
  2. crawlerNo.1(video,audio,image)
  3. 卫星图片重建洛杉矶3D模型,效果就像谷歌地球,港中大团队提出CityNeRF
  4. 树莓派DIY智能无臭猫便盆,拉完粑粑自动通风,成本不到400元
  5. 合格的CTO应该是什么样?雷军王海峰王小川等共谈「技术创新」| CNCC2020
  6. 黄煦涛教授逝世:获誉华人AI视觉鼻祖、一代宗师,完美家庭楷模
  7. 大脑只需单个神经元就可进行XOR异或运算,Science新研究揭开冰山一角,引发热议...
  8. 如何解决多地开视频会议直播问题?
  9. 速读《构建之法:现代软件工程》提问
  10. 【100题】 第四十七题 序列的最长递增、递减序列