webpack 打包优化探索

  • 时间: 2018-05-12 11:46:16

虽然 webpack 的已经升级到了 webpack4 ,而我们目前还在使用 webpack3 ,但其中的优化点都大同小异,升级后同样适用。

性能优化初步原则

  • 减小代码量

  • 减小请求数

  • 最大化利用浏览器缓存

这三条原则永远是一切优化的前提

优化配置

  • 升级 webpack 3 ,优化js的编译能力(Scope Hoisting)

1// 主要配置
2plugins:[
3 new webpack.optimize.ModuleConcatenationPlugin()
4]
  • 合理规划 entry 入口配置(平衡vendor.js, app.js文件的大小)

 1// main.js中第三方公共库提出,作为公共vendor.js, 配合package.json固定第三方库版本,最大化利用浏览器缓存加载js
2entry: {
3 vendor:['vue', 'vue-router', 'vue-resource'],
4 app: './src/main.js'
5}
6// ...
7plugins:[
8 new webpack.optimize.CommonsChunkPlugin({
9 name: ['manifest','vendor'].reverse(),
10 minChunks:Infinity
11 })
12]
  • 打包后文件大小限制,首次加载js+css超过 400k ,单个文件大小超过  300k 将会报错,打包不通过,该配置在build中使用

1performance: {
2 hints: 'error',
3 maxEntrypointSize: 400000,
4 maxAssetSize: 300000
5}

减小代码量

  • 提取 chunk 中使用的公共库(能为chunk代码节约近1/3的代码量)

1new webpack.optimize.CommonsChunkPlugin({
2 name: 'app',
3 async: 'vendor-async',
4 children: true,
5 minChunks: (module, count) => {
6 // 被 2 个及以上 chunk 使用的共用模块提取出来
7 return count >= 2
8 }
9})
  • 减少图片base64的使用,降低限制,限制 2k (vue官方配置是10k,会大大增加js文件体积,移动端对base64的解析成本高)

1  {
2 test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
3 loader: 'url-loader',
4 options: {
5 limit: 2048,
6 name: utils.assetsPath('img/[name].[hash:7].[ext]')
7 }
8 }
  • 生产模式(pro)下第三方库使用已压缩版本,能节约近 20k 文件大小

 1// 开发模式
2resolve: {
3 alias: {
4 'vue': 'vue/dist/vue.esm.js'
5 }
6}
7// 生产模式
8resolve: {
9 alias: {
10 'vue': 'vue/dist/vue.min.js'
11 }
12}
  • 优化 babel-ployfill ,结合  babel-preset-env 实现兼容按需加载,比使用 es2015 能节约近半的大小

1entry: {
2 vendor:['babel-polyfill', 'vue', 'vue-router', 'axios'],
3 app: './src/main.js'
4}
 1// .babelrc
2{
3 "presets": [
4 ["env", {
5 "modules": false,
6 "targets": {
7 "browsers": [
8 "> 1%",
9 "last 3 versions",
10 "Firefox ESR",
11 "not ie < 10"
12 ]
13 },
14 "debug": false,
15 "useBuiltIns": true
16 }],
17 "react",
18 "stage-2"
19 ]
20}
  • 极致压缩js,css代码

 1var os = require('os')
2var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
3
4plugins: [
5 new webpack.optimize.UglifyJsPlugin({
6 // 利用多核能力压缩
7 beautify: {
8 cache: true,
9 workers: os.cpus().length
10 },
11 // 最紧凑的输出
12 beautify: false,
13 // 删除所有的注释
14 comments: false,
15 compress: {
16 // 在UglifyJs删除没有用到的代码时不输出警告
17 warnings: false,
18 // 删除所有的 `console` 语句
19 drop_console: true,
20 // 内嵌定义了但是只用到一次的变量
21 collapse_vars: true,
22 // 提取出出现多次但是没有定义成变量去引用的静态值
23 reduce_vars: true,
24 },
25 sourceMap: true
26 }),
27 new OptimizeCSSPlugin({
28 cssProcessor: require('cssnano')({ zindex: false }),
29 cssProcessorOptions: {
30 safe: true,
31 discardComments: {removeAll: true }
32 }
33 })
34]
  • 第三方库的依赖过滤,如下:

1// 此插件默认全部引入语言库,但我们只用到了中文,最多英文,所以进行了过滤,大大减少了总体代码量
2plugins: [
3 new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /zh|en/)
4]

减少请求数

  • manifest.js文件内联(app.css可以自行选择,当小于10k是最好内联),webpack推荐配置如下:

 1// 引入内联插件
2var HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin')
3
4plugins:[
5 // ...
6 new HtmlWebpackPlugin({
7 // ... 其他不相关配置省略
8 inlineSource:/(app\.(.+)?\.css|manifest\.(.+)?\.js)$/,
9 // ...
10 }),
11 new HtmlWebpackInlineSourcePlugin()
12]

最大化利用浏览器缓存

这样能最大化利用浏览器缓存

 1// 不固定版本,会造成打包后 hash 值变化,浏览器没办法利用本身的缓存加载js,每次上线都会使本地缓存失效,页面加载变慢
2"dependencies": {
3 "moment": "2.17.1",
4 "querystring": "0.2.0",
5 "sprite-cli": "0.1.5",
6 "sticky-state": "2.4.1",
7 "superagent-jsonp": "0.1.1",
8 "underscore": "1.8.3",
9 "vue": "2.0.0",
10 "vue-lazyload": "0.8.3",
11 "vue-router": "2.0.0",
12 "vuex": "2.0.0"
13}

其他优化

zindex被重置问题

由于 cssnano 默认配置,是自动会把 z-index 重置为1,例如:

1classname {
2 z-index:1000;
3}
4
5after
6
7classname {
8 z-index:1;
9}

这时候需要优化cssnano的配置,.postcssrc 如下:

 1/* eslint-disable no-unused-vars */
2module.exports = {
3 plugins: {
4 cssnano: {
5 preset: [
6 'advanced',
7 {
8 zindex: false,
9 }
10 ]
11 }
12 }
13}

使用按需加载js后,打包代码特别大

需要注意的是,当使用按需加载的功能,然后没有提取所有 chunk 包里的 css ,同时又开启了 sourcemap 功能,那么就会造成这种情况

最简单的办法就是,对 css 不使用 sourcemap 功能,例如:

1rules: [
2 {
3 loader: 'postcss-loader',
4 options: {
5 sourceMap: false
6 }
7 }
8]

广告

以下是笔者基于 vue-cli 的模版优化后的 vuereact 的打包工具,用法一致。

以下包集成了以上所有优化,支持单页面及多页面应用,完全兼容 vue-cli 生成的模版项目

zz-webpack-vue

zz-webpack-react

以下是使用本组一个vue-cli生成的项目做的一个优化对比:

优化前:

打包

分析

优化后:

打包

分析

可以查看具体的优化配置,或者直接在项目中尝试使用,有任何问题欢迎随时反馈,目前正在筹划统一升级 webpack4