fast-uglifyjs-plugin
介绍
这里要介绍的是我们开发的一个webpack plugin,用于替换webpack内置的UglifyJsPlugin,加快uglify的效率。
在使用webpack的过程中,我们发现uglify的阶段占据一次打包任务中大部分的时间。
于是我们在webpack内置的UglifyJsPlugin的基础上进行改造,增加了基于多进程的并行uglify和利用缓存实现的按需uglify,最终效率提高非常明显。最近因为内部转为使用webpack 2,我们也实现了对webpack 2的兼容。
性能
插件 | 耗时 |
---|---|
webpack.optimize.UglifyJsPlugin | 7.4 min |
FastUglifyJsPlugin without cache | 4.45 min |
FastUglifyJsPlugin with cache | 36 s |
使用
使用方法跟内置的UglifyJsPlugin基本相同,关于如何使用,请参考文档
实现
下面介绍一下实现过程:
在webpack内部对象compilation
的生命周期optimize-chunk-assets
中,可以对经过当前plugin的chunk进行处理。
chunk在webpack文档中的解释是:
Each chunk manages the composition of a final rendered assets
通俗说就是表示最终输出的对象,而chunk
中的属性chunk.files
表示了最终输出的文件,所以对chunk.files
进行uglify就是webpack内置的UglifyJsPlugin的实现原理。
在这个基础上,我们对uglify的过程进行了改造,改造的内容如下:
开启多个worker进程,将对
chunk.files
的uglify任务分发到多个worker进程中进行,完成后通知主进程进行统一处理。 这样并行的执行uglify,相比于串行,当任务量大的时候,效率提升是很明显的。 关于worker进程的实现,可以查看代码worker.js。因为并不是每次执行webpack任务,所有文件都需要重新uglify,只对修改的文件进行uglify将会对整体效率有巨大的提高。 所以我们增加了文件缓存的功能,webpack每次执行都会缓存上一次uglify的结果,缓存的内容包含了文件名的hash和文件内容的hash,这样在下次uglify时,通过对比hash,如果可以在缓存中找到命中的文件,则跳过uglify直接使用缓存内容。 关于缓存的实现,可以查看代码UglifyCache.js。