前言
在构建大型单页应用(SPA)时,JavaScript 包体积(Bundle Size)往往会随着业务增长而膨胀,导致首屏加载缓慢、白屏时间长。懒加载(Lazy Loading) 是解决这一问题的核心方案。其本质是将代码分割成多个小的 chunk,仅在需要时才从服务器下载。
一、 路由懒加载:按需拆分页面
- 为什么需要路由懒加载?
如果不使用懒加载,所有路由对应的组件都会被打包进同一个 app.js 中。用户访问首页时,浏览器不得不下载整个应用的逻辑,造成严重的性能浪费。
- 实现方式:ES
import()
利用动态导入语法,打包工具(如 Vite 或 Webpack)会自动进行 代码分割(Code Splitting) 。
// router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
// 静态导入:会随着主包一起加载,适合首页
import Home from '@/views/Home.vue';
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// 动态导入:只有访问 /about 路径时,浏览器才会请求该组件对应的 JS 文件
component: () => import('@/views/About.vue')
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
二、 组件懒加载:细粒度控制
有些组件(如弹窗、复杂的图表、第三方重型库)并不需要在页面初次渲染时立即存在。
- Vue 3 的
defineAsyncComponent
在 Vue 3 中,异步组件必须使用 defineAsyncComponent 进行显式声明。
示例
<template>
<div>
<h1>主页面</h1>
<button @click="showChart = true">加载并显示报表</button>
<AsyncChart v-if="showChart" />
</div>
</template>
<script setup lang="ts">
import { ref, defineAsyncComponent } from 'vue';
const showChart = ref<boolean>(false);
// 显式定义异步组件
const AsyncChart = defineAsyncComponent(() =>
import('@/components/BigChart.vue')
);
// 高级配置(可选):带加载状态
const AsyncComponentWithConfig = defineAsyncComponent({
loader: () => import('./components/MyComponent.vue'),
loadingComponent: LoadingComponent, // 加载过程中显示的组件
errorComponent: ErrorComponent, // 加载失败时显示的组件
delay: 200, // 展示加载组件前的延迟时间
timeout: 3000 // 超时时间
});
</script>
-
Vue 2 中直接使用import函数声明异步组件
export default {
components: {
// 定义一个异步组件
'MyLazyComponent': () => import('./components/MyLazyComponent.vue')
}
}
三、 底层原理与分包策略
- 打包工具的配合
当你使用 import() 时:
-
Vite/Rollup :会自动将该组件及其依赖提取到一个独立的
.js文件中。 -
Webpack :会生成一个
chunk,你可以通过"魔法注释"自定义 chunk 的名称:const About = () => import(/* webpackChunkName: "about-group" */ './About.vue')
四、 总结
- 首屏优化:建议首页(Home)使用静态导入,而其他非核心路径、非首屏展示的弹窗/插件全部使用懒加载。
- 用户体验 :使用异步组件时,建议配合
loadingComponent,避免加载过程中组件区域出现突兀的空白 。