Vite 性能篇:提高项目性能!

188 阅读4分钟

分包策略

默认情况下,浏览器重复请求相同名称的静态资源时,会直接使用缓存的资源。利用这个机制我们可以将不会经常更新的代码单独打包成一个 js 文件,这样我们可以减少 HTTP 请求,同时降低服务器压力。

import { defineConfig } from "vite";
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        chunkFileNames: "static/js/[name]-[hash].js",
        entryFileNames: "static/js/[name]-[hash].js",
        assetFileNames: "static/[ext]/[name]-[hash].[ext]",
        // ------ 开始 ------
        manualChunks(id) {
          if (id.includes("node_modules")) {
            return id
              .toString()
              .split("node_modules/")[1]
              .split("/")[0]
              .toString();
          }
        },
        // ------ 结束 ------
      },
    },
  },
});

配置前:

2.png

配置后:js文件由一个被拆分成了多个,并且每次打包并不是所有的文件名都发生了变化

3.png

treeshaking

treeshaking 也被称为 “摇树优化”。简单来讲,就是在保证代码运行结果不变的前提下,去除无用的代码。Vue3 中,许多 ApI 的引入都支持 treeshaking 优化。也就是说只打包你用到的 API,忽略那些没有用到的。

Vue3 会默认使用 Rollup 进行 treeshaking ,不需要额外进行配置。但有一个条件,必须是 ES6 module 模块才行。

以 lodash 为例

npm install lodash
<script setup>
import { concat } from "lodash";
import { onMounted } from "vue";
onMounted(() => {
  console.log(concat([1], [2]));
});
</script>
<style lang="scss" scoped></style>

lodash 打包后的体积大小:

2.png

由于 lodash 是使用 CommonJS 规范的模块,所以无法进行 treeshaking ,Vue 会把整个 lodash 依赖打包进来。整个依赖文件的大小是 70.69 KB 。

这时我们可以使用 ESM 版的 lodash 对比下:

npm install lodash-es
<!-- 组件中使用 -->
<script setup>
import { concat } from "lodash-es";
import { onMounted } from "vue";
onMounted(() => {
  console.log(concat([1], [2]));
});
</script>
<style lang="scss" scoped></style>

打包后的体积如下:

3.png

可以看到依赖体积瞬间变成了 1.44 KB ,原因是只将 lodash concat 模块的代码打包了进来。

GZIP 压缩

gzip 是一种压缩算法,在网络传输中使用非常普遍。需要注意的是,Gzip 压缩仅对于文本类型的资源有明显提升,压缩后的体积大约减小 1/3 左右。对于图片,音视频等媒体资源,本身就采用了有损压缩,所以在使用 gzip 压缩并不能得到很大提升,有时候还会适得其反。而 JS,CSS 资源就非常适合 gzip 压缩。

浏览器解压也需要时间,所以代码体积不是很大的话不建议使用 gzip 压缩,因此我们可以设置一个最小压缩体积。

gzip 压缩后服务端也要进行相应的配置(后端应该知道),否则网页将无法正常打开。

npm i vite-plugin-compression -D
import { defineConfig } from "vite";
import viteCompression from "vite-plugin-compression";

export default defineConfig({
  plugins:{
    viteCompression({
      verbose: true, // 是否在控制台输出压缩结果,默认为true
      disable: false,// 是否禁用压缩,默认为false
      threshold: 10240, // 启用压缩的文件大小限制,默认为0
      algorithm: "gzip", // 采用的压缩算法,默认是gzip
      ext: ".gz",// 生成的压缩包后缀
      filter: "", // 过滤器,对哪些文件进行压缩,默认为/.(js|mjs|json|css|html)$/i’
      deleteOriginFile: false // 压缩后是否删除原文件,默认为false
    }),
  }
});

效果:

4.png

CDN 加速

内容分发网络(Content Delivery Network,简称 CDN)就是让用户从最近的服务器请求资源,提升网络请求的响应速度。通常我们请求依赖模块使用 CDN ,而请求项目代码依然使用自己的服务器。

我们知道文件越大,对于网络带宽和访问速度的要求也就越高。这也是我们优化的方向,我们可以把较大的第三方依赖文件打包上线的时候排除掉,把它们放到 CDN 服务器去,减小整体包的体积,使用 CDN 服务器加快我们的插件访问速度。

以 echarts 插件为例:

npm install echarts
<template>
  <div ref="echart" class="echart"></div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import * as echarts from "echarts";
const echart = ref();
onMounted(() => {
  const myEchart = echarts.init(echart.value);
  myEchart.setOption({
    title: {
      text: "ECharts 入门示例",
    },
    tooltip: {},
    xAxis: {
      data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"],
    },
    yAxis: {},
    series: [
      {
        name: "销量",
        type: "bar",
        data: [5, 20, 36, 10, 10, 20],
      },
    ],
  });
});
</script>
<style lang="scss" scoped>
.echart {
  width: 400px;
  height: 300px;
}
</style>

效果:

5.png

使用 echarts 后打包的项目体积大小:

6.png

我们可以看到使用 echarts 插件后直接导致我们的包的体积增加了将近 1M 的大小。

使用 CDN:

npm install vite-plugin-html rollup-plugin-external-globals --save-dev
// vite.config.js
import { defineConfig } from "vite";
import externalGlobals from "rollup-plugin-external-globals";
import { createHtmlPlugin } from 'vite-plugin-html'

export default defineConfig({
  plugins: [
    createHtmlPlugin({
      minify: true, // html 压缩
      inject:{
        data:{
          echartsSciprt: '<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.3/echarts.min.js"></script>'
        }
      }
    })
  ],
  build: {
    rollupOptions: {
      external: ["echarts"],
      plugins: [
        externalGlobals({
          echarts: "echarts",
        }),
      ]
    },
  }
});
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 注意看这里,没写这个的话,createHtmlPlugin就白写了 -->
    <%- echartsSciprt %>
    <title>Vite + Vue</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

效果:

7.png

我们可以看到 echarts 没有被打包进去,这时候我们看看图表是否正常显示。

npm install serve --config

控制台输入 serve dist 就可以在本地模拟服务器运行

效果:图片也有正常显示出来

8.png