【前端】懒加载(组件/路由/图片等)+预加载 汇总


按需加载=懒加载+预加载

懒加载

组件

组件频繁使用时不建议懒加载,只懒加载低频组件!

  • vue
    defineAsyncComponent+suspense【vue2不支持】+ #default/fallback
    #default 插槽:渲染真正的内容(比如异步组件)
    #fallback 插槽:在内容加载期间显示的占位内容(比如 loading 文案或动画)
<Suspense>
  <template #default>
    <MyComponent />
  </template>
  <template #fallback>
    Loading...
  </template>
</Suspense>


// 异步组件(默认内置 Suspense 支持)搭配 <Suspense> 使用
const MyComponent = defineAsyncComponent(() => import('./MyComponent.vue'))
  • React
    React.lazy 和 Suspense
const MyComponent = React.lazy(() => import('./MyComponent'))

<Suspense fallback={<div>Loading...</div>}>
  <MyComponent />
</Suspense>

路由

//vue
// Vue Router 中使用动态 import 实现懒加载
const routes = [
  {
    path: '/about',
    component: () => import('./views/About.vue')
  }
]

//react routerv6+
const About = React.lazy(() => import('./pages/About'))
//注意:每个使用 React.lazy()的路由组件都要手动包一层 <Suspense>。
<Route path="/about" element={
  <Suspense fallback={<div>Loading...</div>}>
    <About />
  </Suspense>
} />

图片

  • HTML 原生方式(推荐,所有框架都通用)
<img src="image.jpg" loading="lazy" alt="示例图">
  • vue/react
//vue
//插件 vue-lazyload
// main.ts
import VueLazyLoad from 'vue3-lazyload'
app.use(VueLazyLoad)
// 使用
<img v-lazy="imageUrl" />

//react
//1. 原生 loading="lazy"
//2. IntersectionObserver 手写懒加载(更高级)暂略

其他场景

类型VueReact
第三方组件defineAsyncComponent()React.lazy()
Markdown/Code 高亮插件异步加载 PrismJS 等库同上
地图库(如高德)<script async> 动态加载 SDKuseEffect + createElement('script')
iframe/视频等设置 loading="lazy" + 原生IntersectionObserverloading="lazy"/preload="none" // 不预加载视频 /第三方库 react-intersection-observer /原生IntersectionObserver
  • IntersectionObserver
    原生 IntersectionObserver 是 JavaScript 原生浏览器 API,不属于 React、Vue、jQuery 等框架,vue/react都没有自带或者封装它。用来监听某个元素是否进入或离开视口(或另一个指定元素),常用于:
    懒加载图片、视频、iframe
    无限滚动
    进入视口时动画播放
    页面曝光率埋点
    ⚠️注意
    不能监听 display: none 的元素
    滚动容器若是自定义元素,需要设置 overflow: auto/scroll
    IE11 不支持,需要用 IntersectionObserver polyfill
const target = document.querySelector('#myElement');
/*
第一个参数是回调函数,每当被观察的元素进入或离开视口时触发。
entries: 是一个数组,包含每个被观察元素的状态(IntersectionObserverEntry)。
observer: 当前的 IntersectionObserver 实例本身。

第二个参数配置
root: 观察区域。null 表示是浏览器视口(viewport)。
threshold: 触发比例阈值,取值 0 ~ 1。0.1 表示当目标元素有 10% 可见时就触发回调。
*/
const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {//元素已经进入观察区域(例如视口)
      console.log('元素进入视口');
      observer.unobserve(entry.target); // 一次性监听
      //观察器停止监听这个目标
    }
  });
}, {
  root: null, // 默认为视口
  threshold: 0.1, // 元素进入视口 10% 就触发
});

observer.observe(target);//开始观察一个 DOM 元素 target,只要它进入视口就会执行前面的回调。

//多个元素
// 选中所有需要懒加载的图片
const images = document.querySelectorAll('.lazy');
// 遍历每个元素,添加观察
images.forEach(img => observer.observe(img));

预加载

  • 应用场景
场景推荐方式
当前页面关键 JS/CSS/font<link rel="preload">webpackPreload
下个页面可能需要的组件webpackPrefetch / 动态 import()
静态图片<link preload> 或 JS 创建 Image
提前连接 CDN 或后端 API 域名dns-prefetch / preconnect
用户 hover/点击前加载手动 import()/fetch()
  • html文件
类型技术/方式说明
HTML 资源级别<link rel="preload">提前加载关键资源,支持 js/css/font/image/video 等。
<link rel="prefetch">低优先级加载未来可能用到的资源(如下一页)。
<link rel="dns-prefetch">提前进行 DNS 查询,加快第三方资源访问。
<link rel="preconnect">提前进行 TCP + TLS 握手。
<link rel="prerender">预渲染整个页面(较少使用,Chrome 支持有限)。
  • JS文件
    安装Webpack 的“魔法注释”写法,用于控制异步模块的加载优先级
    这类注释只在 Webpack 构建时生效,属于 Webpack 的“魔法注释”
    生成的 HTML 中会自动插入 <link rel="preload"> 或 <link rel="prefetch"> 标签
import(/* webpackPrefetch: true */ './HeavyComponent');
import(/* webpackPreload: true */ './CriticalComponent');

webpackPrefetch: 低优先级预加载,浏览器空闲时加载(推荐用于未来页面组件)
webpackPreload: 高优先级并行加载,立即加载(推荐用于当前页面关键模块)

  • vue/react懒加载+预加载组合,使加载更聪明
const Page = () => import(/* webpackPrefetch: true */ './Page.vue');

const LazyPage = React.lazy(() => import(/* webpackPrefetch: true */ './Page'));

// 可搭配使用:使用 prefetch 手动提前加载,否则空闲才加载 
import('./Page');
  • 图片
<link rel="preload" as="image" href="/images/banner.jpg">
const img = new Image();
img.src = '/images/banner.jpg';
  • 组件:vue/react也是通过提前触发 import() 方式实现(参考上方 webpackPrefetch),也可以组合搭配上懒加载
  • 视频
<video preload="auto" src="video.mp4" />
<!-- 
none	不预加载任何数据
metadata	只加载元数据
auto	浏览器自己决定(尽量预加载)
-->
  • 路由也是用路由预加载确实可以通过 Webpack 的魔法注释来实现搭配懒加载
  • 字体 也是<link rel="preload" as="font" href="font.woff2" type="font/woff2" crossorigin="anonymous">
  • 页面可见性触发
    结合 IntersectionObserver,提前加载资源
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      fetch('/api/data.json'); // 或 import()
      observer.unobserve(entry.target);
    }
  });
});
observer.observe(document.querySelector('#future-content'));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七灵微

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值