我正在参加「掘金·启航计划」
现在很多小伙伴都已经使用 Vite + Vue3 开发项目了,如果你是 “前端架构师” 或者是 “团队核心” 的话,不得不可考虑的一个问题就是性能优化。
说到前端性能优化,个人认为主要有两个方面:
本篇文章主要讲述的是生产环境下 Vite + Vue3 打包优化之-依赖分包策略、CDN在线加速 。
依赖分包策略
在没有配置构建工具的分包功能时,构建出来的文件将无比巨大且是独立的一个 js 和 css 文件(如下图),这样本地加载文件时会存在巨大的压力。
默认情况下,浏览器重复请求相同名称的静态资源时,会直接使用缓存的资源。利用这个机制,我们可以将不经常更新的代码单独打包成一个 JS 文件,这样就可以减少 HTTP 请求,同时降低服务器压力。
Vite 官方文档 -> 构建选项 -> build.rollupOptions中这样描述:自定义底层的 Rollup打包配置。这与从 Rollup 配置文件导出的选项相同,并将与 Vite 的内部 Rollup 选项合并。查看 Rollup 选项文档获取更多细节。也就是说 Vite 底层已经集成了 Rollup 的一部分功能,我们直接配置即可。
我这里的 Rollup 相关配置如下(仅供参考):
rollupOptions: {
output: { // 静态资源分类打包
chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件如:字体、图片、样式等
manualChunks(id) { // 创建自定义的公共 chunk,将静态资源分拆打包:将 node_modules 中的代码单独打包成一个 JS 文件
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
}
}
}
配置好你的build.output参数,执行命令
npm run build
我们就可以看目录结构了。
output.manualChunks 创建自定义的公共 chunk
-
当值为对象形式时,每个属性代表一个 chunk,其中包含列出的模块及其所有依赖。chunk 的名称由对象属性的键决定。
manualChunks({ manualChunks: { lodash: ['lodash'] } })
-
当该选项值为函数形式时,每个被解析的模块都会经过该函数处理。如果函数返回字符串,那么该模块及其所有依赖将被添加到以返回字符串命名的自定义 chunk 中。
-
以下例子,创建一个命名为
vendor
的 chunk,它包含所有在node_modules
中的依赖manualChunks(id) { if (id.includes('node_modules')) { return 'vendor'; } }
-
以下例子,将静态资源分拆打包:将 node_modules 中的代码单独打包成一个 JS 文件
manualChunks(id) { if (id.includes('node_modules')) { return id.toString().split('node_modules/')[1].split('/')[0].toString(); } }
-
2 output.chunkFileNames 对代码分割中产生的 chunk 自定义命名
- 值是一个匹配模式,或值是一个函数,对每个 chunk 调用以返回匹配模式。
- 这种模式支持以下的占位符:
[format]
:输出(output)选项中定义的格式(format),例如es
或cjs
。[hash]
:仅基于最终生成的 chunk 内容的哈希值,其中包括renderChunk
中的转换部分和其依赖文件哈希值。你也可以通过例如[hash:10]
设置一个特定的哈希值长度。[name]
:chunk 的名称。它可以通过output.manualChunks
选项显示的设置,或者通过插件调用this.emitFile
设置。否则,它将会根据 chunk 的内容确定。
3 output.entryFileNames 指定 chunks 的入口文件模式、
- 值是一个匹配模式,或值是一个函数,对每个 chunk 调用以返回匹配模式。
- 这种模式支持以下的占位符:
[format]
:输出(output)选项中定义的格式(format),例如es
或cjs
。[hash]
:仅基于最终生成的入口 chunk 内容的哈希值,其中包括renderChunk
中的转换部分和其依赖文件哈希值。你也可以通过例如[hash:10]
设置一个特定的哈希值长度。[name]
:入口文件的文件名(不包含扩展名),除非当入口文件为对象时,才用来定义不同的名称。
4 output.assetFileNames 用于自定义构建结果中的静态资源名称
- 值是一个匹配模式,或值为一个函数,对每个资源调用以返回匹配模式。
- 这种模式支持以下的占位符:
[extname]
:包含点的静态资源文件扩展名,例如.css
[ext]
:不包含点的文件扩展名,例如css
[hash]
:基于静态资源内容的哈希。也可以通过例如[hash:10]
设置一个特定的哈希值长度[name]
:静态资源的名称,不包含扩展名
正斜杠 /
可以用来划分文件到子目录。
CDN在线加速
内容分发网络(Content Delivery Network,简称 CDN),是构建在数据网络上的一种分布式内容分发网,它可以让用户从最近的服务器请求资源,以提升网络请求的响应速度。
通常情况下,我们请求依赖模块使用 CDN ,而请求项目代码依然使用自己的服务器。
在 Vite + Vue3 项目开发过程中,像 element-plus、lodash-es 等工具库,会有很大的文件依赖。我们可以尝试通过配置 CDN 的方式来减轻”单系统”的请求压力。(一般我们的项目只有一个服务器,称为单系统)
安装 CDN 管理插件
# npm 方式
npm i vite-plugin-cdn-import -D
# yarn 方式
yarn add vite-plugin-cdn-import -D
以 lodash-es 为例,在 vite.config.ts 文件中,配置对应 module 的 CDN
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 使用 CDN 插件
import vitePluginCDN from 'vite-plugin-cdn-import'
export default defineConfig({
// plugins 需要用到的插件数组
plugins: [
vue(),
vitePluginCDN({
// 配置需要 CDN 加速的模块
modules: [
{ name: 'lodash-es', var: '_', path: 'https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js'}
]
})
]
})
通过 npm run build
命令构建成功后,Vite 会自动将 CDN 资源通过 script 标签插入到 html 中(如下图)。这样请求 lodash 资源就会产生加速 buff,而且项目的打包体积也会大大减少。
使用 CDN 的问题:一但依赖网站出现问题,我们的项目也就不行了,建议留下备用方案,以便维护。如果公司有条件,可以使用公司自己的 CDN 以确保安全性