开发阶段,我们更多的是关注开发体验,在生产环境,我们更多的是关注运行时的性能。 开发阶段的构建性能问题,Vite 内部已经做了相当多的优化,实现了项目秒级启动与毫秒级热更新。这里我们介绍下线上环境的项目加载性能优化。
关于性能优化:
- 网络优化。包括
HTTP2
、DNS 预解析
等手段。 - 资源优化。包括
构建产物分析
、资源压缩
、产物拆包
、按需加载
等优化方式。
网络优化
-
HTTP2
HTTP1.1存在队头阻塞的问题,同一个TCP只能处理一个http请求,也就是说当前请求没有处理完其他请求都是处于阻塞状态中。浏览器对同一个域名下的并发请求数量也是有限制,如Google最多只能同时处理6个请求并发,超出6个只能排队或者等待发送请求。
因此,在 HTTP 1.1 协议中,队头阻塞和请求排队问题很容易成为网络层的性能瓶颈。而HTTP2就是为了解决这些问题而出现的。
-
多路复用:将数据分为多个二进制帧,多个请求和响应的数据帧在同一个TCP通道中传输,解决了队头阻塞的问题,在HTTP2中浏览器不在限制同一域名下并发请求数量限制。
-
Server push:服务端推送能力。
在Vite中我们可以通过vite-plugin-mkcert
在本地serve中开启HTTP2
pnpm i vite-plugin-mkcert -D
然后在vite.config.js中配置使用
// vite.config.js
import { defineConfig } from "vite";
import vue from '@vitejs/plugin-vue'
import mkcert from "vite-plugin-mkcert";
export default defineConfig({
plugins: [vue(), mkcert()],
server: { // https 选项需要开启
https: true
}
});
- DNS预解析
浏览在向跨域的服务器发送请求时,首先会进行DNS解析,将服务器域名解析为对应的IP地址。通过dns-prefetch
将DNS解析提前,降低DNS解析延迟的时间。
<!-- href 为需要预解析的域名 -->
<link rel="dns-prefetch" href="https://fonts.com/">
一般情况下 dns-prefetch
会与preconnect
搭配使用,前者用来解析 DNS,而后者用来会建立与服务器的连接,建立 TCP 通道及进行 TLS 握手,进一步降低请求延迟。使用方式如下所示:
<link rel="preconnect" href="https://fonts.com/" crossorigin>
<link rel="dns-prefetch" href="https://fonts.com/">
资源优化
- 产物分析报告
用rollup-plugin-visualizer
来进行产物分析。使用方式如下:
//vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { visualizer } from "rollup-plugin-visualizer";
export default defineConfig({
plugins: [vue(),
visualizer({
// 打包完成后自动打开浏览器,显示产物体积报告
open: true,
})
]
})
接下来我们来看下Element-plus 完整引入和自动引入打包后的对比
完整引入后的打包分析
自动引入后的打包分析
- 资源压缩
- javascript文件
在Vite生产环境构建中,会自动对js产物进行压缩
// vite.config.js
export default {
build: {
// 类型: boolean | 'esbuild' | 'terser'
// 默认为 `esbuild`
minify: 'esbuild',
// 产物目标环境
target: 'modules',
// 如果 minify 为 terser,可以通过下面的参数配置具体行为
// https://terser.org/docs/api-reference#minify-options
terserOptions: {}
}
}
- CSS代码
// vite.config.js
export default {
build: {
// 设置 CSS 的目标环境
cssTarget: ''
}
}
- 图片压缩
图片资源是一般是产物体积的大头,如果能有效地压缩图片体积,那么对项目体积来说会得到不小的优化。而在 Vite 中我们一般使用 vite-plugin-imagemin
来进行图片压缩
- 产物拆包
如果不对产物拆包会有以下问题
- 首屏加载的代码体积过大,即使是当前页面不需要的代码也会进行加载
- 线上缓存复用率极低,改动一行代码即可导致整个 bundle 产物缓存失效
Vite 中内置如下的代码拆包能力
- CSS 代码分割,即实现一个 chunk 对应一个 css 文件
- 默认有一套拆包策略,将应用的代码和第三方库的代码分别打包成两份产物,并对于动态 import 的模块单独打包成一个 chunk
- 按需加载
在一个完整的 Web 应用中,对于某些模块当前页面可能并不需要,如果浏览器在加载当前页面的同时也需要加载这些不必要的模块,那么可能会带来严重的性能问题。一个比较好的方式是对路由组件进行动态引入,