记录一次Webpack插件优化的经历

去年12月份,我一个才毕业半年的前端新人接触了Webpack。跟着网上教程学习时,遇到了一个难题:文件名加上hash编码后,屡次打包会有以前残留的文件。 css

当时看的那篇文章,并无提到clean-webpack-plugin,因此我就傻傻的手动删除。还很奇怪为何这么严重的问题没人说过……其实就是当时google的关键字有问题,没搜到正确的结果。前端

不过也是那次误打误撞,让我开始维护一个本身的Webpack插件——webpack-remove-hashed-files。具体功能能够看我以前的文章webpack

原本这个插件吧,功能也不是很复杂,因此我开发好初版后就没管了。只有后面收到一封邮件,按要求我新增了白名单的功能。接着就搁置了三个月吧。git

不过呢,昨天在新项目里须要用到几个本地的图片,因而就发现了一个buggithub

就是说,我在项目中原本要用file-loader去处理js和css中引入的本地图片,将他们打包到dist文件夹下。而后呢,我打算把它们都放在dist/assets/images子文件夹下。因而就配置file-loader,option为{name: 'assets/images/[name].[ext]'}web

然而就是这个配置致使个人删除插件出了问题。segmentfault

原本我插件的设计是遍历dist目录,将全部文件的文件名与Webpack的compliation.assets的键名比较,若是文件名可以对应于某一个键名,说明是本次打包的内容,将其保留。其余的都删除。这是不考虑白名单的思路。数组

可是,不知道为何,file-loader处理后的文件,在assets中是以相似于assets/images/a.jpg的键名保存的,这就致使遍历dist文件夹时,我是用a.jpgassets/images/a.jpg作比较。虽然这是同一个文件,但实际上被误认为两个文件,从而致使删除bug。学习

那么我该怎么解决呢?测试

首先要明确问题出现所涉及到的两个角色:file-loaderwebpack-remove-hashed-files。其次,可以修改的是file-loader的options与删除插件的源码。而个人目的就是要把全部图片都存放在dist/assets/images文件夹下,因此file-loader的options是不能修改的,应该重构插件的源码来适应file-loader的配置。

说实话,昨天想了一天才解决好这个问题。由于一直没明白,file-loader究竟是怎么作到又改文件名又能建立个新文件夹的……

继续说怎么修改删除插件的源码吧。我苦思冥想N个小时后,决定推翻之前的判断逻辑。由于我想到了一个更简单的判断因素,并且这个因素才是删除插件的核心,只是一直被我忽略了。那就是【文件路径】。

compliation.assets中,每一键对应一个文件对象,其中有一个字段existsAt代表打包后的文件所在的绝对路径。那么咱们先将这些路径保存到一个数组dirArrays中,而后在遍历dist下全部文件时,在dirArrays中搜索每一个不在白名单中的文件的绝对路径,若是存在则保留;不存在则说明不是本次打包的内容,应该删除。

听上去是否是既不影响原有功能,并且还能解决file-loader的bug问题?另外还比以前的逻辑要简单一些。

至于为何说文件路径是删除插件的核心?由于插件实质上作了两件事:比较assets与dist中全部文件、删除非本次打包产生的文件。本来只有在删除时才要调用fs.unlink方法,传入文件路径参数。而如今在比较的时候就使用了文件路径。说明它贯穿了本插件的全部流程,说是核心也不为过了。

以上就是本次优化插件的完整记录了,总结一下就是本身造的轮子要多测试多维护,这样才能有理由写推广的文章,让更多人去使用hhh。

另外,在遇到bug后我分析了一下竞品clean-webpack-plugin,发现它的思路跟去年我看得时候相比,仍是默认在生命周期emit时遍历目标文件夹dist,若是文件不在白名单里就直接删除。这点也是它可以不受file-loader影响的缘由。

但也是我一开始文章中说过的,本次打包与上一次打包也许只有一个文件被修改,实际上只要删除旧的这一个文件就行,但clean-webpack-plugin是将全部文件都删除了。我以为这一点在大项目中仍是会致使打包时间问题的,因此就本身造了个轮子。

还发现了一点,就是判断了是否有compiler.hooks,这是Webpack 4的新特性。后面我再修补下这个问题。

最后,感谢阅读。

相关文章
相关标签/搜索