组件懒加载
一、路由级懒加载(框架原生支持)
- Vue Router 动态导入
使用import()
语法实现路由级代码分割,访问对应路由时加载独立分包。
1const router = new VueRouter({
2 routes: [
3 { path: '/about', component: () => import('./views/About.vue') }
4 ]
5});
React Router v6+ 方案
结合 React.lazy
和 Suspense
实现按需加载:
1const Home = React.lazy(() => import('./components/Home'));
2<Suspense fallback={<Loading />}>
3 <Route path="/home" element={<Home />} />
4</Suspense>
二、组件级懒加载(细粒度优化)
- 动态导入语法
在组件使用前通过import()
延迟加载,适用于弹窗等非首屏内容:
1
2const Dialog = () => import('./Dialog.vue');
3
4
5const Editor = React.lazy(() => import('./Editor'));
条件触发加载
结合用户交互(如点击按钮)触发组件加载:
1function loadComponent() {
2 import('./ChartComponent').then(module => {
3 const Chart = module.default;
4
5 });
6}
三、构建工具配置(底层支持)
-
Webpack 代码分割
- 通过
splitChunks
配置公共模块分包:
- 通过
1optimization: {
2 splitChunks: {
3 chunks: 'all',
4 cacheGroups: {
5 vendor: { test: /node_modules/, name: 'vendors' }
6 }
7 }
8}
- 使用
/* webpackChunkName: "chunk-name" */
自定义分包名称。
-
Vite 自动分包
动态导入自动生成独立 chunk,无需额外配置。四、优化策略
-
预加载关键资源
对高优先级分包添加webpackPreload
注释,提前加载:
1import( './CriticalComponent');
-
缓存优化
- 分包命名包含哈希值(如
[contenthash]
),利用浏览器长效缓存。 - Webpack 5 配置
cache: { type: 'filesystem' }
加速二次构建。
- 分包命名包含哈希值(如
错误处理与降级
封装加载逻辑,捕获网络异常并提供重试机制:
1const loadWithRetry = async (url, retries = 3) => {
2 try {
3 return await import(url);
4 } catch (err) {
5 if (retries > 0) return loadWithRetry(url, retries - 1);
6 throw err;
7 }
8};
总结
前端实现懒加载需结合框架特性与构建工具:
- 路由/组件级动态导入 触发自动分包(Vue/React 原生支持);
- 构建配置 优化拆分策略(Webpack/Vite 定制化);
- 预加载+缓存 平衡性能与用户体验。
通过分层加载策略,可降低首屏资源体积 30%~50%34,显著提升交互响应速度。
图片的懒加载
一使用第三方库 vue-lazyload
适用场景:需要快速集成和丰富功能(加载态、错误处理)
实现步骤:
- 安装依赖
1npm install vue-lazyload
全局配置
1
2import VueLazyload from 'vue-lazyload'
3
4Vue.use(VueLazyload, {
5 preLoad: 1.3,
6 error: require('@/assets/error.png'),
7 loading: require('@/assets/loading.gif'),
8 attempt: 3,
9 observer: true,
10 observerOptions: {
11 rootMargin: '0px 0px 200px 0px'
12 }
13})
组件中使用
1<template>
2 <img v-lazy="imageUrl" :alt="description">
3</template>
二使用原生 Intersection Observer API(推荐)
原理:通过浏览器原生 API 监听图片是否进入可视区域,触发加载
优点:无依赖、性能好、支持动态内容
实现步骤:
- 注册全局自定义指令
1
2Vue.directive('lazy', {
3 inserted: (el, binding) => {
4 const observer = new IntersectionObserver((entries) => {
5 entries.forEach(entry => {
6 if (entry.isIntersecting) {
7 const img = new Image()
8 img.src = binding.value
9 img.onload = () => {
10 el.src = binding.value
11 observer.unobserve(el)
12 }
13 img.onerror = () => console.error('图片加载失败')
14 }
15 })
16 }, {
17 rootMargin: '0px 0px 200px 0px'
18 })
19
20 observer.observe(el)
21 }
22})
组件中使用
1<template>
2 <img v-lazy="imageUrl" :alt="description">
3</template>
4
5<script>
6export default {
7 data() {
8 return {
9 imageUrl: 'https://example.com/image.jpg',
10 description: '示例图片'
11 }
12 }
13}
14</script>
个人笔记记录 2021 ~ 2025