前言
本篇文章是笔者在使用 vue3 + vite 实际开发过程中的一些经验分享,涵盖 vite 构建优化配置项的实践,以及一些开发中实用技巧的分享。
gzip 压缩
未开启压缩时:通过vite打包之后,vite会提示开启 gzip压缩之后的文件大小,可以看到文件体积将会显著下降
接下来,我们使用 vite-plugin-compression 进行 gzip 压缩
javascript
import viteCompression from 'vite-plugin-compression'
export default defineConfig({
plugins: [
viteCompression(),
],
})
通过 gzip 压缩之后,文件会被转化为 gz 压缩包,体积会明显减少,虽然是压缩包格式,但浏览器解压时间非常快,几乎可以忽略。所以开启 gzip 压缩 是有必要尝试的。
动态导入
使用动态导入,在 webpack 或 vite 这样的打包工具之中,都会自动开启代码分割。
路由懒加载
Vue Router 支持开箱即用的动态导入,这意味着你可以用动态导入代替静态导入:
javascript
// 将
// import UserDetails from './views/UserDetails.vue'
// 替换成
const UserDetails = () => import('./views/UserDetails.vue')
const router = createRouter({
// ...
routes: [{ path: '/users/:id', component: UserDetails }],
})
异步导入组件
javascript
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() =>
import('./components/MyComponent.vue')
)
代码分割
所谓代码分割,实际上就是将大文件拆解为小文件,充分利用 http2 多路复用的特点,更高效的加载文件。以前一个大文件需要加载很长的时间,拆解为小文件,多个文件一起加载,就可以极大的提高网站的加载效率。
除了动态导入能够自动开启代码分割以外,我们还可以通过对 vite 进行配置来手动进行代码分割。
manualChunks 自定义分割
通过对 manualChunks 对象进行配置,自定义代码分割规则。key 为自定义名称,value 以数组形式配置,子元素可以填写 package.json名称 或 src/相对路径下的指定文件
ts
// vite.config.ts
build: {
// rollup 配置
rollupOptions: {
output: {
manualChunks: {
// vue vue-router合并打包
vue: ['vue', 'vue-router'],
lodash: ['lodash'],
// 两个文件合并成一个文件
a: ['src/components/a.vue','src/components/b.vue'],
...
}
}
}
}
又或者你可以采用函数配置方法,可以更细粒度的去配置代码分割规则
ts
// vite.config.ts
build: {
// rollup 配置
rollupOptions: {
output: {
manualChunks(id, { getModuleInfo }) {
const match = /.*.strings.(\w+).js/.exec(id)
if (match) {
const language = match[1] // e.g. "en"
const dependentEntryPoints = []
const idsToHandle = new Set(getModuleInfo(id).dynamicImporters)
for (const moduleId of idsToHandle) {
const { isEntry, dynamicImporters, importers } = getModuleInfo(moduleId)
if (isEntry || dynamicImporters.length > 0) dependentEntryPoints.push(moduleId)
for (const importerId of importers) idsToHandle.add(importerId)
}
if (dependentEntryPoints.length === 1) {
return `${dependentEntryPoints[0].split('/').slice(-1)[0].split('.')[0]}.strings.${language}`
}
if (dependentEntryPoints.length > 1) {
return `shared.strings.${language}`
}
}
},
}
}
}
设置路径别名
这样可以在引入文件时,不再需要使用相对路径,自定义起点路径,方便各个层级的代码引入。比如以下的代码示例,可以方便我们使用src目录下的文件。
ts
// vite.config.ts
// 设置路径别名
resolve: {
alias: [
{
find: '@',
replacement: path.resolve('./src'),
},
],
}
ts
import { apiGetInfo } from '@/apis/funtion'
import { useStore } from '@/stores/index'
引入全局公共样式
所有预处理器选项支持additionalData选项,该选项可用于为每个样式内容注入额外的代码。以下以 less 为例子,注入全局的公共样式,使得各个 less 文件都可以直接使用公共文件中的样式,不用手动引入。
ts
export default defineConfig({
css: {
preprocessorOptions: {
less: {
additionalData: `@import "@/styles/common.less";`,
}
},
},
})
less
// src\styles\common.less
.ellipsis {
overflow: hidden; /* 超出部分被隐藏 */
text-overflow: ellipsis; /* 被裁剪的文本使用省略号表示 */
white-space: nowrap; /* 禁止换行,文本在一行内显示 */
}
less
// 任意less文件
.text {
.ellipsis;
}
terser 压缩
build.minify 中配置 terser,可以将打包体积降到最小。通过对 build.terserOptions 进行配置,可以更详细的配置你想要的效果。
build.minify 中配置 terser 时必须先安装 Terser。
shell
npm i terser -D
ts
// vite.config.ts
build: {
minify: 'terser', //是否禁用最小化混淆,esbuild打包速度最快,terser打包体积最小。
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
format: {
comments: false, // 删除所有注释
},
},
},
强制预构建插件包
我们可以通过对 vite.config.ts 中 optimizeDeps 的配置来优化依赖项。
默认情况下,不在 node_modules 中的,链接的包不会被预构建。使用此选项可强制预构建链接的包。
使用强制预构建,可以提高后续页面的加载性能,因为Vite会将那些具有许多内部模块的 ESM 依赖项转换为单个模块。有些包将它们的 ES 模块构建为许多单独的文件,彼此导入。一旦模块变得也来越多,众多的HTTP请求导致浏览器将不堪重负,而通过预构建可以将其构建为单个模块,现在我们只需要一个HTTP请求。
如果你使用的是一个有很多深层导入的库,你也可以指定一个尾部的 glob 模式来一次性地预构建所有深层导入。这将避免在使用新的深层导入时不断地预构建。
ts
export default defineConfig({
optimizeDeps: {
include: ['my-lib/components/**/*.vue'],
},
})
依赖预构建仅适用于开发模式,并使用 esbuild 将依赖项转换为 ES 模块。在生产构建中,将使用 @rollup/plugin-commonjs。
其他打包配置优化
ts
build: {
chunkSizeWarningLimit: 2000,// chunk 超过 2000kb 之后进行提示
cssCodeSplit: true, //css 拆分
sourcemap: false, //不生成sourcemap
assetsInlineLimit: 5000, //小于该值 图片将打包成Base64
},
后记
以上就是本次文章的全部内容,感谢观看,本篇文章均为个人实践经验分享,如有不对还请见谅,欢迎留言探讨。