打包体积优化(Vue)

1,101 阅读4分钟

1 分析图

在项目打包时终端输入命令 npm run report 或者 npm run build --report 打包生成dist文件夹,在dist文件夹下会出现一个report.html,就是分析图文件。

备注:如果是vite创建的,安装rollup的包npm install rollup-plugin-visualizer --save-dev,并且在vite.config.js或者vite.config.ts内输入

import { visualizer } from "rollup-plugin-visualizer";
export default defineConfig({
  plugins: [
    vue(), visualizer()
    ],
    ...
})
   

运行npm run build会得到一个stats.html文件,打开就可以看到资源占比

得到性能图后,整个项目的parsed size为2.05MB

性能图

1

分析图中占据面积越大的文件,就代表占据的更大的体积。

2 优化

2.1 按需加载

图中可以发现ant-design-vue在项目中占据了很大的体积,因此使用按需加载的方式减小体积。 具体的按需加载方式可以详见官网。 使用按需加载之后,整个项目的parsed size为1.77MB

LMI@@N0RHP0{LWO}~Z(`~7V.png

2.2 使用CDN

  1. 项目中另一块巨大的面积的消除可以使用CDN的方式,首先卸载相应的包 npm uninstall @antv/x6 axios vuex vue-router
  2. unpkg.com/ 或者www.bootcdn.cn/ 去找相应的CDN (一定要注意版本号,并且需要指定版本号)
  3. 在public/index.html中的或者部分引入这些CDN,比如
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/4.1.3/vue-router.global.prod.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/vuex/4.0.2/vuex.global.prod.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/antv-x6/1.32.11/x6.min.js"></script>
注意,准备部署到线上前记得更换为.prod版本的CDN

4. 在vue.config.js中配置axios VueRouter Vuex @antv/x6

module.exports = defineConfig({
  configureWebpack: {
    externals: {
      axios: "axios",
      "vue-router": "VueRouter",
      Vuex: "Vuex",
      vue: "Vue",
      "@antv/x6": "X6",
    },
});
  1. 使用:
    import { createRouter, createWebHistory } from "vue-router";
    

在使用CDN引入后,项目体积大大减小,整个项目的parsed size为991KB,比一开始减小了53%的体积。 image.png

同时观察devtool中的network选项,这几个cdn引入的包都从缓存中读取(disk cache) image.png

CDN 不同包的选取

CDN.png 在网站上有许多不同后缀的包名字,需要谨慎选择:

  • 比如说带cjs的,是用CommonJS语法编写的,如果在项目中引入会报错Uncaught ReferenceError: module is not defined at vue-router.cjs.js:1:1,点进入发现module.exports = require('../dist/vue-router.cjs'),这是由于浏览器不支持CommonJS语法,无法使用 module exports require global.
  • 在比如带esm的CDN,需要在script标签里面加 type="module"比如
    <script type="module" src="https://cdn.bootcdn.net/ajax/libs/vue-router/4.1.3/vue-router.esm-browser.js"></script>
    
    但是我加了之后还是有报错Uncaught TypeError: Failed to resolve module specifier "vue". Relative references must start with either "/", "./", or "../". ,故放弃
  • 最后使用带global的CDN,全程无报错。

注意点

  1. 引入后发现报错就重启这个项目
  2. 网站上有些CDN的链接会报跨域的错误,直接换一个链接
  3. 建议引入Vue的CDN
  4. 尽量选择国内的CDN,有些国外的速度很慢
  5. 使用带.min的包

关于ant-design-Vue

官网不建议使用CDN的引入方式,因为这样无法按需加载,而且难以获得底层依赖模块的 bug 快速修复支持。单纯是这个问题,其实不影响。而且vite下的CDN引入完全可以避免这个问题。

但是在webpack下引入的时候,要注意:

<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.5/dayjs.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.5/plugin/customParseFormat.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.5/plugin/weekday.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.5/plugin/localeData.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.5/plugin/weekOfYear.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.5/plugin/weekYear.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.5/plugin/advancedFormat.min.js"></script>

<link href="https://cdn.bootcdn.net/ajax/libs/ant-design-vue/3.1.1/antd.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/ant-design-vue/3.1.1/antd.min.js"></script>

额外要引入关于时间的包,并且一定要在ant-design-vue引入之前!ant-design-Vue改为CDN引入后也是正常使用,,但是在自己的实际的使用中,只引入 <script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.5/dayjs.min.js"></script>也是可以正常工作的。这之后体积进一步减小到150K

image.png

2.3 gzip(需要后端配合)

image.png

将之前的分析图的HTML的Treemap sizes切换到Gzipped,可以发现gzip可以进一步压缩项目体积,到只有60多KB

步骤:

  1. npm uninstall --save-dev compression-webpack-plugin 安装compression-webpack-plugin。
  2. 配置vue.config.js
    ...
    const CompressionWebpackPlugin = require("compression-webpack-plugin");
    const productionGzipExtensions = ["js", "css"];
    module.exports = defineConfig({
       ...
      configureWebpack: {
        plugins: [
          new CompressionWebpackPlugin({
            filename: "[path].gz[query]",
            algorithm: "gzip",
            test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"), // 匹配文件名
            threshold: 10240, // 对超过10K的数据进行压缩
            minRatio: 0.8, //极小比
          }),
        ],
      },
      
    });
    
    
    1. npm打包,会发现多出了几个.gz的文件

    image.png

    4. 后端配置 建议是nginx

2.4 其他优化

  • 删除一些没用到的包,发现打包完的文件中有jquery,但是项目中并没有用到,直接npm uninstall jquery
  • 图片的压缩
  • 路由懒加载
  • 去掉console.log

2.5 Lighthouse

优化前的lighthouse评分

~L4`BO_M)A0JLUEKMNT}O4X.png

打包部署后,使用lighthouse看一下评分,还是有提高的。

image.png

network部分的效果,耗时其实都很少了

image.png

3 意义

  1. 项目体积越小,客户端收到项目文件速度会越快,有利于增加首屏渲染速度
  2. 减小了服务器的存储压力