记一次管理平台webpack优化

最近对公司商务运营管理平台做了部分优化,优化后包体积减小为原来的43%,性能有很大提升。

优化前

原配置文件中已包含部分优化,包括

  • 使用compression-webpack-plugin开启gzip压缩
  • 使用svg-sprite-loader将svg文件打包成雪碧图
  • 使用optimization.splitChunks做代码分割

......
在此基础上仍有很大优化空间,首先借助 webpack-bundle-analyzer 将打包后的内容展示为方便交互的树状图,我们可以很直观的看到有哪些比较大的模块,然后做针对性优化。

image.png

可以看到总体为7.71M,其中node_modules占用较多,所以可进行较明显的构建优化.

CDN+external

> CDN 的工作原理是将源站的资源缓存到位于全球各地的 CDN 节点上,用户请求资源时,就近返回节点上缓存的资源,而不需要每个用户的请求都回您的源站获取,避免网络拥塞、缓解源站压力,保证用户访问资源的速度和体验。

可以看到打包模块中将一些引入库也打包进来,这里我们可以采用引入外链cdn取消对较大依赖模块的打包。
在vue.config.js中添加如图配置


image.png

同时在public中的index.html中引入cdn链接


image.png

需要注意点,在 html 中配置的 CDN 引入脚本最好要在 body 内的最底部,因为:

  • 如果放在 body 上面或 header 内,则加载会阻塞整个页面渲染。
  • 如果放在 body 外,则会在业务代码被加载之后加载,模块中使用了该模块将会报错
  • CDN最好采用公司内部CDN,这里使用了vue及element官网链接和服务较好的bootcdn

按需引入

很多element组件只用到了较少一部分,所以可采用按需引入
安装插件babel-plugin-component后修改.babelrc文件

{
    "presets": [],
    "plugins": [
        [
          "component",
          {
            "libraryName": "element-ui",
            "styleLibraryName": "theme-chalk"
          }
        ]
      ]
}

在需要的地方引入,例

import { Loading } from "element-ui";

语言包优化

某些场景下,语言包会占用整个包体积的非常大一部分。实际上库本身的逻辑不会很大,moment 就是一个很好例子。如果是新项目,推荐使用dayjs替代moment,它只有2k,此处用了不影响原逻辑我们仍延用moment,把不使用的语言包过滤掉,推荐使用 ContextReplacementPlugin,他可以过滤掉不使用的语言,也可以用webpack的IgnorePlugin插件

image.png

const ContextReplacementPlugin = require("webpack/lib/ContextReplacementPlugin");
config.plugin("ignore").use(new ContextReplacementPlugin(/moment[/\\]locale$/, /zh-cn$/));
image.png

过滤后仅为原来25%

去除console

日常开发为了方便调试,代码中会有一些console,但是在生产环境中为了信息安全这些console是不能出现的,这里我们使用terser-webpack-plugin插件来去掉console。该插件通常用语代码压缩,有类似功能的插件还有uglifyjs-webpack-plugin,但uglifyjs-webpack-plugin缺点是不支持es6
安装

npm install terser-webpack-plugin --save-dev

使用

const TerserPlugin = require("terser-webpack-plugin");

vue.config.js的configureWebpack中添加

 optimization: {
            minimizer: [
                new TerserPlugin({
                    terserOptions: {
                        compress: {
                            pure_funcs: ["console.log"]
                        }
                    }
                })
            ]
        },

打包时发现报错


image.png

排查后发现原因是webpack和terser插件的版本差异,terser目前最新版为5.0.2,但我们项目中使用的事webpack4.x,所以要安装terser插件的4.x版本,安装后重新build正常。
在打包后的dist文件夹app.js中搜索console.log未发现说明生效。


image.png

压缩图片

项目中有较多小于2k的icon和小图片可使用file-loaderurl-loader处理

image.png

原理是url-loader可将小于limit的图片转成base64格式,大于limit的图片由file-loader编译
配置如下

const imagesRule = config.module.rule("images");
        imagesRule.uses.clear();
        imagesRule
            .use("file-loader")
            .loader("url-loader")
            .options({
                limit: 16384, // 小于2k转长base64
                fallback: {
                    loader: "file-loader",
                    options: {
                        outputPath: "static/img"
                    }
                }
            });

打包后包大小减少了0.2M,效果不大,但是对图片处理更明显的优点是减少http请求以及在图片渲染过程中的性能提升。

最终效果

image.png

以上方式可使项目在花费较小时间成本的情况下让性能有较大提升,如对性能还有更高要求,仍有很多方式可进一步优化。

你可能感兴趣的:(记一次管理平台webpack优化)