组件懒加载

一、路由级懒加载(框架原生支持)

  1. 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>

二、组件级懒加载(细粒度优化)

  1. 动态导入语法
    在组件使用前通过 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}

三、构建工具配置(底层支持)

  1. Webpack 代码分割

    • 通过 splitChunks 配置公共模块分包‌:
 1optimization: {
 2  splitChunks: {
 3    chunks: 'all',
 4    cacheGroups: {
 5      vendor: { test: /node_modules/, name: 'vendors' }
 6    }
 7  }
 8}
  • 使用 /* webpackChunkName: "chunk-name" */ 自定义分包名称‌。
  1. Vite 自动分包
    动态导入自动生成独立 chunk,无需额外配置‌。

    四、优化策略

  2. 预加载关键资源
    对高优先级分包添加 webpackPreload 注释,提前加载‌:

 1import( './CriticalComponent');
  1. 缓存优化

    • 分包命名包含哈希值(如 [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};

总结

前端实现懒加载需结合框架特性与构建工具:

  1. 路由/组件级动态导入‌ 触发自动分包(Vue/React 原生支持)‌;
  2. 构建配置‌ 优化拆分策略(Webpack/Vite 定制化)‌;
  3. 预加载+缓存‌ 平衡性能与用户体验‌。
    通过分层加载策略,可降低首屏资源体积 30%~50%‌34,显著提升交互响应速度。

图片的懒加载

一使用第三方库 vue-lazyload

适用场景‌:需要快速集成和丰富功能(加载态、错误处理)
实现步骤‌:

  1. 安装依赖
 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. 注册全局自定义指令
 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