在做首屏优化时,为了减少初始代码的加载,我们一般都会使用组件懒加载来优化。但只靠组件懒加载来优化是不够的。下面我们一起来看下组件懒加载为什么不是首屏优化的唯一选择。
组件懒加载
组件懒加载(Component Lazy Loading)是一种优化技术,用于在需要时才加载组件,而不是初始化时就加载所有组件
但在首页功能模块很多时,即使每个组件都是懒加载,页面还是需要等待组件加载成功之后才能展示出来。
而且在视口以外的组件也会加载,这就造成了浏览器的不必要的渲染。
//组件懒加载
const Articals = React.lazy(() => import('../common/Articals'));
//直接在页面调用
<React.Suspense fallback={<div>Loading...</div>}>
<ArticalsLazyComponent title="Layz Articles3"/>
</React.Suspense>
为了减少首屏的dom渲染和组件的不必要加载,我们可以使用视口检测结合组件懒加载,进一步提升首屏渲染性能。
视口检测结合组件懒加载
只有在视口之内才真正加载需要的组件
//组件懒加载
const ArticalsLazyComponent = React.lazy(() => import('../common/ArticalsLazy'));
//在视口检测器内使用
<IntersectionView>
<React.Suspense fallback={<div>Loading...</div>}>
<ArticalsLazyComponent title="Layz Articles3"/>
</React.Suspense>
</IntersectionView>
视口检测器组件代码实现
import { useEffect, useRef, useState } from "react"
interface IntersectionObserverInit {
root?: Element | Document | null;
rootMargin?: string; // 根元素的外边距,同css的margin
threshold?: number | number[];
}
interface LazyLoadProps {
children:React.ReactNode; // 子组件
observerOptions?: IntersectionObserverInit;
}
const defaultOptions: IntersectionObserverInit = {
root: null, // 根元素,默认为浏览器视窗
rootMargin: '0px', // 根元素的外边距
threshold: 0.1, // 交叉比例阈值,当目标元素进入或离开根元素时触发回调
}
const Index:React.FC<LazyLoadProps> = (props) =>{
const {children,observerOptions=defaultOptions} = props
const [show,setShow] = useState<boolean>(false)
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
let entry = entries[0]
console.log('isIntersecting',entry.isIntersecting)
if(entry.isIntersecting){
setShow(true)
stop()
}
},{...observerOptions})
const stop = ()=>{
if(ref.current){
observer.unobserve(ref.current)
}
}
return ()=>{
stop()
}
}, []);
return (
<div className="relative w-full min-h-[400px]" ref={ref}>
{show && children}
</div>
)
}
export default Index
使用视口检测器我们可以很方便的控制组件加载时机,减少不必要的代码加载,提高首屏渲染性能。