【webpack4x】部分底层原理及手写一个简单打包工具
目录
一、 如何编写一个loader
二、 如何编写一个Plugin
三、 Bundler源码编写(模块分析)
一、 如何编写一个loader
1.额外知识点,此处不能是箭头函数,因为我们里面要用到this指向问题,webpack会对里面的this进行变更,去用this调用一些方法
2. 自己写一个loader
那么如何使用自己写的loader
继续加强,可以配置自己的参数
并通过this.query接收使用
其他:可以通过this获得很多东西(查阅官方文档)
官方建议获取参数使用的一种方法
this.callback(使用比较多)
return的时候,只能return一个参数,我们写一个等价上面return的语句如下(我们通过它第三个参数可以把整个sourceMap都返回出去)
3. this.async(),使得有时候我们可以做个异步的处理
上述写法是错误的,因为代码是从上而下执行的,执行到下面的时候,没有return任何东西,解决办法
4. 多个loader,配置规则(先使用的放在下面,执行顺序是从下往上执行loader)
但是上述配置的规则,每次都要匹配路径,继续优化
通过resolveLoader这个属性,找loader的时候,会先去node_modules找,然后再去loader目录下找,下面使用的loader就可以直接写loader,不再去添加繁琐的路径匹配
5.自定义loader的用武之地
场景1:有时候,我们需要对业务代码做一个异常监控,在外层加上try catch,使得出异常时候,能及时捕获。那么,一种思路是,我们可以实现一个loader,当判断当前是一个function的时候,给他外层包裹上try,catch,使得所有function都运行在try catch中,伪代码例如:
场景2:文字国际化
二、如何编写一个Plugin
场景: 我们想在打包结束以后,生成一个版权的文件
1. 写一个插件的格式大概如下:
2. 使用plugin
3. 参数如何使用
4.回到一开始的场景: 当打包结束的时候,往dist目录下放一个版权的文件copyright.txt
4.1 上述compiler.hooks.emit是一个异步事件,后面使用tapAsync方法,里面传两个参数,第一个参数是插件的名字,第二个参数传的是一个方法, () => {} 该方法有2个参数,第一个参数是complication,第二个参数是一个回调函数cb。
4.2 complication.assets可以看到打包后要输出的文件数,可以往里面添加一个我们要输出的文件。
里面的参数很多(具体看官方文档),这里主要用到2个,一个source表示里面的内容,一个size表示里面内容的大小
4.3 最后,还要调用一下回调函数
5.看一个同步的方法
6. 插件调试,例如想看下complation.assets里面是否有输出
6.1 添加一个打包命令
// 详细代码为,传递一些node参数 --inspect表示要开启node调试工具 第二个参数--inspect-brk表示在第一行打个断点
"script": {
"debug": "node --inspect --inspect-brk node_modules/webpack/bin/webpack.js "
}
6.2
6.3 运行命令,
打开浏览器
点击该图标进入调试页面
三、Bundler源码编写(模块分析)
1. 编写代码 bundler.js
2. 装一些插件
3. 简述上面工作:
- 3.1 读取了入口文件index.js下面的代码
- 3.2 使用parser.parse方法,将代码内容转换为一个语法树
- 3.3 使用traverse对语法树的内容进行分析,把import的内容分析出来,并将结果以key-value的形式保存在一个对象中,key为解析出来的路径,value为处理过后当前项目下的路径
- 3.4 分析完依赖以后,还吧es6的语法转换成了浏览器可以识别的语法
4. 刚刚只分析了入口文件依赖等信息,接下来的工作是把所有的模块都进行分析,最后得到一个依赖图谱
然后console一下graphArray是这样的
这个图谱不太利于查看,可以再进行下结构转换,放到graph中