vue-cli 4.5 打包优化,项目实战

2,681 阅读3分钟
  • 背景

    优化是起初是因为项目在测试环境首屏在测试环境加载过长,测试同学吐槽,然后着手优化的,说干就干,优化搞起来,首屏优化对用户体验还是很重要的。
  • 分析现状

    项目是用的 vue-cli4.5 版本,下面是 devlopment 环境打包后的结构
    ├─ dist
    │ ├─ assets
    │ │ └─ js
    │ │ ├─ app.js
    │ │ └─ chunk-vendors.js
    │ ├─ favicon.ico
    │ └─ index.html

未优化前的体积,总共加起来有5.43M 挺大的 image.png

同事安利了一款 webpack-bundle-analyzer 神器分析代码,可以直观的看到文件中的依赖和大小。下面工具分析后的图,工具用法自行看文档。推荐大家使用。 image.png

app.js 主要是一些业务相关的代码。size: 3.56M
chunk-vendors.js 主要是一些第三方的依赖文件。size:1.83M 工具调试代码如下,仅供参考:

 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    plugins.push(new BundleAnalyzerPlugin(
      {
        analyzerMode: 'server',
        analyzerHost: '127.0.0.1',
        analyzerPort: 8889,
        reportFilename: 'report.html',
        defaultSizes: 'parsed',
        openAnalyzer: true,
        generateStatsFile: false,
        statsFilename: 'stats.json',
        statsOptions: null,
        logLevel: 'info'
      }
    ))

问了下同事,说测试环境方便调试,路由没用懒加载,用的require方式导入,生产动态切换路由懒加载。 由于在打包优化方面也没太多经验,然后疯狂百度,查阅webpack 文档和 vue-cli文档,相关资料调试。

以下是分析和观察到一些问题:

  1. area.js 存储到资源服务器,目前是七牛云

image.png

area.js 这里很多个是因为业务特殊原因,需要动态切换省市县层级,area目录也有215k。

优化area之后的:

image.png

  1. 第三方插件 cdn 引入

修改 vue.config.js chainWebpack 配置
vue.config.js 文件

 //第三方库cdn外部引入,减少打包体积
      config.set('externals', {
        vue: "Vue",
        'vue-router': 'VueRouter',
        vuex: 'Vuex',
        axios: "axios",
        swiper: 'Swiper',
        vant: 'vant'
      })

HTML

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport"
    content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover" />
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  <link rel="stylesheet" href="//at.alicdn.com/t/font_2423676_hx4ccbq3p0r.css">
  <link rel="stylesheet" href="https://unpkg.com/swiper@5.3.8/css/swiper.css" />
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/vant@2.12/lib/index.css"
  />

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6/dist/vue.min.js"></script>
  <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.2.0/vuex.min.js"></script>
  <script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js"></script>
    <!-- 引入 Vue 和 Vant 的 JS 文件 -->
  <script src="https://cdn.jsdelivr.net/npm/vant@2.12/lib/vant.min.js"></script>
  <script src="https://unpkg.com/swiper@5.3.8/js/swiper.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue-awesome-swiper/dist/vue-awesome-swiper.js"></script>
  <script type="text/javascript">
    Vue.use(window.VueAwesomeSwiper);
  </script>
  <title><%= htmlWebpackPlugin.options.title %></title>
</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
      Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
  <!-- built files will be auto injected -->
</body>
<script src="https://res2.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
</html>

优化之后:

image.png

好家伙:vender.js 减少了700多k

  1. 压缩代码,目前只是在生产做压缩,本地调试不方便就没压缩了
    configureWebpack 加入代码

 config.mode = 'production'
      let prodPlugins = [
        // 压缩js/css/html
        new CompressionPlugin({
          // filename: '[path].gz[query]',// 目标文件名
          // algorithm: 'gzip',// 使用gzip压缩
          test: /\.js$|\.html$|.\css/, // 匹配文件名
          threshold: 10240, // 对超过10k的数据压缩
          minRatio: 0.8, // 只有压缩率比这个值小的资源才会被处理
          deleteOriginalAssets: true // 不删除源文件
        })
      ]
  1. 删除 prefetch 具体可看 vue-cli 配置,chainWebpack中加入
// 移除 prefetch 插件,避免占用多余的带宽
config.plugins.delete('prefetch');
  1. 去掉console.log,目前生产开启
    chainWebpack 中修改
  //去除console.log代码
    if(process.env.NODE_ENV === 'production') {
      config.optimization
      .minimizer('terser')
      .tap(args => {
        Object.assign(args[0].terserOptions.compress, { // 生产模式 console.log 去除
          // warnings: false , // 默认 false
          // drop_console:  ,
          // drop_debugger: true, // 默认也是true 
          pure_funcs: ['console.log']
        })
        return args
      })
    }

目前只在生产能看到效果,因为本地打包后,发现生成的文件都没prefetch 的,生产的话就一次性prefeth 所有chuck块。

  • 生产环境效果走起

主要还是以 生产环境 为基准:看看优化前后效果
优化前的:1.14M image.png

优化后的:725.11kb

image.png

生产大小优化了 414.89 kb,效果还是有的。

  • 总结

    经过这次项目优化,对webpack 配置更加了解了,学到很多。比如路由懒加载,开发和生产环境如何权衡优化。优化的道路还很长,还有很多要学;觉得有用的话,麻烦大佬们点个赞吧。