主题
项目优化
主要从以下几个方面考虑:
- 构建层面:使用 Vite 的代码分割、Tree Shaking,配置合理的 chunk 拆分策略,第三方库使用 CDN。
- 加载性能层面:路由懒加载、组件异步加载、图片懒加载和压缩。
- 运行时性能层面:Vue 3 用 v-memo、shallowRef 优化,大列表用虚拟滚动,避免不必要的响应式。
- 网络层面:接口请求防重复、数据缓存、使用防抖节流。
- 监控层面:使用 Lighthouse 分析性能,监控首屏加载时间、白屏时间等关键指标。
1. 构建优化
- visualizer:分析打包体积,找出大体积依赖。
- 减少打包体积:
- Tree Shaking:确保代码和依赖库支持 Tree Shaking。
- 按需引入第三方库(如 Element Plus、Lodash)。
- sourcemap:某些情况下,生产环境可关闭或者调整 sourcemap 以减少体积。
- 去除 console 和 debugger。
- 代码分割:合理拆分 chunk,减少首屏加载体积。
- compression:生成 gzip 或 brotli 静态资源。
js
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://www.npmjs.com/package/rollup-plugin-visualizer
import { visualizer } from 'rollup-plugin-visualizer'
// https://www.npmjs.com/package/vite-plugin-compression
import compression from 'vite-plugin-compression'
export default defineConfig({
plugins: [
vue(),
// 打包体积分析
visualizer({
open: true,
gzipSize: true,
brotliSize: true,
}),
],
build: {
// 代码分割
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router', 'pinia'],
'ui-vendor': ['element-plus'], // 或 arco-design-vue
'utils': ['axios', 'dayjs'],
},
},
},
// 压缩配置
minify: 'terser', // 'oxc' | 'terser' | 'esbuild'
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
// chunk 大小警告阈值
chunkSizeWarningLimit: 1000,
},
})js
// vue.config.js
module.exports = {
productionSourceMap: false,
configureWebpack: {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
},
elementUI: {
test: /[\\/]node_modules[\\/]element-ui[\\/]/,
name: 'element-ui',
priority: 20,
},
},
},
},
},
}2. 加载性能优化
路由懒加载
js// Vue Router 懒加载 const routes = [ { path: '/dashboard', component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Dashboard.vue'), }, { path: '/user', component: () => import(/* webpackChunkName: "user" */ '@/views/User.vue'), }, ]组件懒加载
jsimport { defineAsyncComponent } from 'vue' // 异步组件 const HeavyComponent = defineAsyncComponent(() => import('./components/HeavyComponent.vue'))图片懒加载和压缩
- 使用
Intersection Observer API实现图片懒加载。 - 使用工具(如
ImageOptim、TinyPNG)或构建插件(如vite-plugin-imagemin)压缩图片体积。
- 使用
3. 运行时性能优化
vue
<script setup>
import { ref, computed, shallowRef, shallowReactive } from 'vue'
// 1. 使用 shallowRef/shallowReactive 处理大型数据
const bigList = shallowRef([])
// 2. 计算属性缓存
const filteredList = computed(() => {
return bigList.value.filter((item) => item.active)
})
// 3. v-memo 优化列表渲染(Vue 3.2+)
</script>
<template>
<!-- 使用 v-once -->
<div v-once>This content will not re-render.</div>
<!-- 使用 v-memo 缓存不变的部分(超大列表) -->
<div v-for="item in list" :key="item.id" v-memo="[item.id, item.selected]">
{{ item.name }}
</div>
<!-- 使用 v-show 而非 v-if(频繁切换的元素) -->
<div v-show="isVisible">Content</div>
<!-- 虚拟滚动(处理大列表) -->
<virtual-list :items="bigList" :item-height="50" />
</template>jsx
import { memo, useMemo, useCallback, lazy, Suspense } from 'react'
// 1. React.memo 避免不必要的重渲染
const ExpensiveComponent = memo(
({ data }) => {
return <div>{data.name}</div>
},
(prevProps, nextProps) => {
return prevProps.data.id === nextProps.data.id
},
)
// 2. useMemo 缓存计算结果
const memoizedValue = useMemo(() => {
return expensiveCalculation(data)
}, [data])
// 3. useCallback 缓存函数
const handleClick = useCallback(() => {
doSomething(param)
}, [param])
// 4. 懒加载组件
const LazyComponent = lazy(() => import('./LazyComponent'))
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
)
}4. 网络优化
- 防重复请求。
- 缓存接口数据。例如:用户信息、角色权限等不频繁变化的数据。
- CDN 加速静态资源和接口请求。
5. 代码质量优化
- Tree Shaking 和按需引入,减少冗余代码。
- 防抖、节流,优化高频事件处理。
- 代码规范:
- 使用
ESLint规范代码风格,Prettier格式化代码。 - 使用
TypeScript提升代码健壮性。 - 使用 Git Hooks(如
Husky)在提交前进行代码检查和测试,确保代码质量。
- 使用
