刷刷题38(前端实现分包及组件懒加载的核心方案&&图片懒加载)

组件懒加载

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

  1. Vue Router 动态导入

    使用 import() 语法实现路由级代码分割,访问对应路由时加载独立分包‌。

javascript 复制代码
const router = new VueRouter({
  routes: [
    { path: '/about', component: () => import('./views/About.vue') } // 生成独立 chunk
  ]
});

React Router v6+ 方案

结合 React.lazySuspense 实现按需加载‌:

javascript 复制代码
const Home = React.lazy(() => import('./components/Home'));
<Suspense fallback={<Loading />}>
  <Route path="/home" element={<Home />} />
</Suspense>

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

  1. 动态导入语法

    在组件使用前通过 import() 延迟加载,适用于弹窗等非首屏内容‌:

javascript 复制代码
// Vue
const Dialog = () => import('./Dialog.vue');

// React
const Editor = React.lazy(() => import('./Editor'));

条件触发加载

结合用户交互(如点击按钮)触发组件加载‌:

java 复制代码
function loadComponent() {
  import('./ChartComponent').then(module => {
    const Chart = module.default;
    // 渲染组件
  });
}

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

  1. Webpack 代码分割

    • 通过 splitChunks 配置公共模块分包‌:
css 复制代码
optimization: {
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      vendor: { test: /node_modules/, name: 'vendors' }
    }
  }
}
  • 使用 /* webpackChunkName: "chunk-name" */ 自定义分包名称‌。
  1. Vite 自动分包

    动态导入自动生成独立 chunk,无需额外配置‌。

    四、优化策略

  2. 预加载关键资源

    对高优先级分包添加 webpackPreload 注释,提前加载‌:

go 复制代码
import(/* webpackPreload: true */ './CriticalComponent');
  1. 缓存优化

    • 分包命名包含哈希值(如 [contenthash]),利用浏览器长效缓存‌。
    • Webpack 5 配置 cache: { type: 'filesystem' } 加速二次构建‌。

错误处理与降级

封装加载逻辑,捕获网络异常并提供重试机制‌:

javascript 复制代码
const loadWithRetry = async (url, retries = 3) => {
  try {
    return await import(url);
  } catch (err) {
    if (retries > 0) return loadWithRetry(url, retries - 1);
    throw err;
  }
};

总结

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

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

图片的懒加载

一使用第三方库 vue-lazyload

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

实现步骤‌:

  1. 安装依赖

    npm install vue-lazyload

全局配置

javascript 复制代码
// main.js
import VueLazyload from 'vue-lazyload'

Vue.use(VueLazyload, {
  preLoad: 1.3, // 预加载高度比例
  error: require('@/assets/error.png'), // 错误占位图
  loading: require('@/assets/loading.gif'), // 加载中占位图
  attempt: 3, // 重试次数
  observer: true, // 开启 IntersectionObserver
  observerOptions: {
    rootMargin: '0px 0px 200px 0px'
  }
})

组件中使用

xml 复制代码
<template>
  <img v-lazy="imageUrl" :alt="description">
</template>

二使用原生 Intersection Observer API(推荐)

原理 ‌:通过浏览器原生 API 监听图片是否进入可视区域,触发加载

优点 ‌:无依赖、性能好、支持动态内容

实现步骤‌:

  1. 注册全局自定义指令
javascript 复制代码
// main.js
Vue.directive('lazy', {
  inserted: (el, binding) => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const img = new Image()
          img.src = binding.value
          img.onload = () => {
            el.src = binding.value // 加载完成后替换src
            observer.unobserve(el) // 停止观察
          }
          img.onerror = () => console.error('图片加载失败')
        }
      })
    }, { 
      rootMargin: '0px 0px 200px 0px' // 提前200px加载
    })

    observer.observe(el)
  }
})

组件中使用

xml 复制代码
<template>
  <img v-lazy="imageUrl" :alt="description">
</template>

<script>
export default {
  data() {
    return {
      imageUrl: 'https://example.com/image.jpg',
      description: '示例图片'
    }
  }
}
</script>
相关推荐
Exclusive_Cat1 小时前
失败的面试经历(ʘ̥∧ʘ̥)
面试·职场和发展
网际游侠1 小时前
一份C#的笔试题及答案
面试·c#·笔试
大龄大专大前端2 小时前
JavaScript闭包的认识/应用/原理
前端·javascript·ecmascript 6
字节源流2 小时前
【SpringMVC】常用注解:@SessionAttributes
java·服务器·前端
肥肠可耐的西西公主2 小时前
前端(vue)学习笔记(CLASS 4):组件组成部分与通信
前端·vue.js·学习
烛阴2 小时前
JavaScript 函数绑定:从入门到精通,解锁你的代码超能力!
前端·javascript
花椒和蕊2 小时前
【vue+excel】导出excel(目前是可以导出两个sheet)
javascript·vue.js·excel
泫凝2 小时前
使用 WebP 优化 GPU 纹理占用
前端·javascript
magic 2453 小时前
CSS块元素、行内元素、行内块元素详解
前端·css
returnShitBoy3 小时前
前端面试:React hooks 调用是可以写在 if 语句里面吗?
前端·javascript·react.js