浅谈Webpack打包优化技巧

前端的打包工具从之前的browserify、grunt、gulp到现如今的rollup、webpack,涌现出了很多优秀的打包工具,而目前最火的无疑是webpack,无论是当前热门的框架还是工具库很多都选择了它作为打包工具,因此在开发中webpack作为打包工具是一个很好的选择。在最近的项目开发中我也用到了webpack,其中也碰到了不少优化方面的问题,这里总结一下webpack打包优化的一些细节和方法。

首先,这次项目用到的是vue的全家桶,在webpack的配置方面直接用的是 vue-cli 生成的默认配置,项目打包完成后发现生成的 vendor.js 文件体积特别大,其次打包过程相当缓慢,因此想尝试各种方式对其进行优化。

定位体积大的模块

要想对打包体积进行优化,首先得找到体积大的模块,在这里我们可以使用webpack插件 webpack-bundle-analyzer 来查看整个项目的体积结构对比,它是以treemap的形式展现出来,很形象直观,还有一些具体的交互形式。既可以查看你项目中用到的所有依赖,也可以直观看到各个模块体积在整个项目中的占比。

浅谈Webpack打包优化技巧

该插件的使用方法可以直接通过 npm install webpack-bundle-analyzer --save-dev 安装,并在webpack的配置信息中的 plugins: [new BundleAnalyzerPlugin()] 中添加即可。对于 vue-cli 中的配置方式,默认是安装了该插件,但是没有启用,找到 config/index.js 文件在 build 下面会有 bundleAnalyzerReport 的配置,默认是 process.env.npm_config_report ,这里建议在 package.json 的 scripts 中添加一行 "analyz": "npm_config_report=true npm run build" ,这样每次想启用该插件时只需要 npm run analyze 即可。

提取公共模块

对于webpack,它在模块化打包上有两点是其核心功能,一是它支持大量的模块类型,无论是 TypeScript 、 CoffeeScript 还是 sass 、 stylus 等语言它都支持,二是它可以通过配置来控制打包文件的粒度,这个下面会讲到。

在开发中我们往往会将所有的依赖库单独提取出来,而不与我们的项目代码混在一起,这时我们会用到一个webpack自带的插件 CommonsChunkPlugin ,从名字上就可以看出它是一个提取公共模块的插件。从它的文档中可以看出可以传入一个对象最为参数,在使用中常用的三个参数分别为:

name(names)

minChunks

chunks

name 好理解,指的就是最后打包文件的名字,而如果使用的是 names 的话,传入的必须是一个字符串数组。 minChunks 如果传入的是一个数字的话,指的是如果该模块被其他模块的引用次数达到了这个数值的话该模块就会被打包。如果传入的是一个函数的话,其返回值必须是布尔类型来指明这个模块是否应该被打包进公共模块。而 chunks 则会指定一个字符串数组,如果设置了该参数,则打包的时候只会从其中指定的模块中提取公共子模块。

下面通过几个实例来说明这个插件是如何工作的。

假设有两个模块 chunk1.js 和 chunk2.js 以及两个项目文件 a.js 和 b.js ,结构大致如下:

// a.js require('./chunk1'); require('./chunk2'); require('jquery'); // b.js require('./chunk1'); require('./chunk2'); require('vue'); // webpack配置如下 module.exports = { entry: { main: './main.js', main1: './main1.js', jquery:["jquery"], vue:["vue"] }, output: { path: __dirname + '/dist', filename: '[name].js' }, plugins: [ new CommonsChunkPlugin({ name: ["common","jquery","vue","load"], minChunks:2 }) ] };

最终的打包结果是: jquery 被打包到 jquery.js , vue 被打包到 vue.js , common.js 打包的是公共模块(chunk1和chunk2)。使用该插件打包时,会将满足 minChunks 的模块打包到 name 数组的第一个块里,然后数组后面的依次打包,首先从 entry 中找,如果没有则产生一个空块。 name 数组中最后一个块打包的是webpack的runtime代码,在使用的时候必须先加载该块。

现在看一看 vue-cli 对于该插件的配置文件:

new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: function (module, count) { // 将node_modules中的依赖模块全部提取到vendor文件中 return ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname, '../node_modules') ) === 0 ) } }), // webpack在使用CommonsChunkPlugin时会生成一段runtime代码,并且打包进vendor中。 // 这样即使不改变vendor代码,每次打包时runtime会变化导致vendor的hash变化,这里 // 把独立的runtime代码抽离出来来解决这个问题 new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', chunks: ['vendor'] }),

移除不必要的文件

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/3db9f96c1a1ee3a53c5fa2dfbaa07f1e.html