webpack包教不包会(二)性能优化最佳实践

1,673 阅读3分钟

在第一篇我们实现了一个基于react的webpack配置,只是满足了我们基本的开发需求,你肯定曾经或正在遭受webpack冷启动和热更新龟速,打包时间过久的痛苦,那么这篇我们来总结一些,如何使它打包更快更小,让我们的老伙计爆发出更强的战斗力。

小即是快!如果你装的包有问题,可能是版本不兼容,真的坑...

开发阶段性能优化

监控面板

清晰的展示打包的效果,让我们更快的定位到问题的位置,给出明确的优化建议

speed-measure-webpack-plugin

速度分析(webpack5到目前还不支持),使用smp.wrap包裹。

const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
 
const smp = new SpeedMeasurePlugin();
 
const webpackConfig = smp.wrap({
  plugins: [
    new MyPlugin(),
    new MyOtherPlugin()
  ]
});

打包时控制台能看到具体耗时

image.png

webpack-bundle-analyzer

生成一个漂亮的分析图(可以查看开启gzip之后的大小)

image.png

开启通知

webpack-build-notifier

打包结束之后可以给出提示

plugins: [
    new WebpackBuildNotifierPlugin({
      title: "爸爸,打包成功了",
      suppressSuccess: true, // don't spam success notifications
    }),
  ]

image.png

开启多核压缩

uglifyjs-webpack-plugin 官方推荐

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        parallel: true, // 开启多核
      }),
    ],
  },
};

开启打包进度监控

progress-bar-webpack-plugin

打包时会显示打包进度

image.png

清晰的开发面板

webpack-dashboard

打开一个清晰的监控面板

image.png

上线阶段

前端缓存负载(性能优化杀手锏)

知道什么时候可以去更新离线缓存

// npm install webpack-nano webpack-manifest-plugin --save-dev

const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const options = { ... };

module.exports = {
	// an example entry definition
	entry: [ 'app.js'	],
  ...
  plugins: [
    new WebpackManifestPlugin(options)
  ]
};

1、在dist文件下,生成一个mainfest.json的文件,做打包记录

2、利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致。我们可以使用缓存功能

optimization: {
      runtimeChunk: 'single',
     splitChunks: {
       cacheGroups: {
         vendor: {
           test: /[\\/]node_modules[\\/]/,
           name: 'vendors',
           chunks: 'all',
         },
       },
     },
    },

加载loading

html-webpack-plugin

这个生成模版html时用到

const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
  new HtmlWebpackPlugin({
    title: 'webpack包教不包会(一)',
    template: './src/index.html',
    loading: {
       html: '加载中...'
    }
  }),
],
// 模版html中引用
<body>
   <div id="root">
     <%= htmlWebpackPlugin.options.loading.html %>
   </div>
</body>

分析打包结果

webpack-chart(官方推荐)

使用

// package.json 配置命令
 "chart": "webpack --profile --json > stats.json"

根目录下生成stats.json

image.png

将文件上传到生成地址

会生成一个可交互饼图

image.png

或者使用官方分析工具(除了丑还挺好用的)

image.png

缩小文件范围

test exculde include

{
  // 用正则去匹配要用该 loader 转换的 CSS 文件
  test: /\.less$/,
  use:['style-loader', 'css-loader', 'less-loader'],
  exclude: /node_modules/,
  include: './src'
},

压缩

项目上线,一键压缩代码,图片处理 js、css happypack ts-loader optimize-css-assets-wenpack-plugin

配置多入口

可以用于获取更小的 bundle,以及控制资源加载优先级

 entry: {
    index: './src/index.js',
    another: './src/another-module.js',
  },

提取公共模块

SplitChunksPlugin

optimization: {
   splitChunks: {
     chunks: 'all',
   },
 },

mini-css-extract-plugin

用于将 CSS 从主应用程序中分离。

预获取/预加载模块

在引用时

  • prefetch(预获取):将来某些导航下可能需要的资源
  • preload(预加载):当前导航下可能需要资源
import(/* webpackPrefetch: true */ '模块地址');
import(/* webpackPreload: true */ '模块地址');

treeShaking 自动剔除无用代码

在webpack4之后的版本,mode设置production会自动进行treeshaking

对于treeShaking的解释,官网用了很形象的一个例子

你可以将应用程序想象成一棵树。绿色表示实际用到的 source code(源码) 和 library(库),是树上活的树叶。灰色表示未引用代码,是秋天树上枯萎的树叶。为了除去死去的树叶,你必须摇动这棵树,使它们落下。

总结

性能优化是个很宏大的命题,webpack作为构建阶段的常用工具,掌握其优化方法很有必要,熟练的使用webpack,其实还是要掌握一些好用的loader和plugin,用到什么就去下载什么😂源码地址

参考资料

wepack中文文档

深入浅出 Webpack