开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
一、路由懒加载
1、背景
随着前端应用体积的增大,资源加载的优化是我们必须要面对的一个问题,动态加载
就是一种常用的解决方式。
在React16.6.0版本中,新增了React.lazy函数,它能让你像常规组件一样处理动态引入的组件,配合 webpack 的 Code Splitting,只有当组件被加载,对应的资源才会导入,从而达到懒加载的效果。
2、使用
// 使用懒加载
const OtherComponent = React.lazy(() => import('./OtherComponent'));
// 之前不使用懒加载
import OtherComponent from './OtherComponent';
- 语法
- React.lazy 接受一个函数作为参数,这个函数需要调用import()。
- React.lazy 方法返回的是一个lazy组件的对象,类型是react.lazy,并且 lazy 组件具有 _status 属性。并且与 promise 类似,有 Pending,Resolved,Rejected 三个状态,分别代表组件的加载中,已加载、加载失败三个状态。
- 注意
- React.lazy 需要配合
Suspense
组件一起使用,在 Suspense 组件中渲染 React.lazy 异步加载的组件。单独使用 React.lazy ,React 会给出报错提示。
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
- OtherComponent是通过懒加载加载进来的,所以渲染页面的时候可能会有延迟,但使用了Suspense之后,可优化交互。
- 在外面使用Suspense标签,并在fallback中声明OtherComponent加载完成前做的事,即可优化整个页面的交互。
3、实现原理
1、利用 Webpack 的动态加载
懒加载使用了 import() 语法,webpack 检测到这种语法会自动代码分割。
使用这种动态导入语法代替以前的静态引入,可以让组件在渲染的时候,再去加载组件对应的资源,这个异步加载流程的实现机制是通过webpack实现的。
webpack 是通过创建 script 标签来实现动态加载的,找出依赖对应的chunk信息,然后生成script标签来动态加载chunk,每个chunk都有对应的状态:未加载,加载中,已加载。
2、Suspense 组件
Suspense 内部主要通过捕获组件的状态去判断如何加载,上面我们提到 React.lazy 创建的动态加载组件具有Pending,Resolved,Rejected三种状态,当这个组件的状态为Pending时显示的是 Suspense 中 fallback 的内容,只有状态变为 Resolved 才会显示组件。
3、Error Boundaries 处理资源加载失败场景
从 React 16 开始,引入了 Error Boundaries 概念,它可以捕获它的子组件中产生的错误,记录错误日志,并展示降级内容。
错误边界避免一个组件错误导致整个页面白屏不能使用等情况,使用优雅降级的方式呈现备用的 UI,错误边界可以在渲染期间、生命周期和整个组件树的构造函数中捕获错误。自 React 16 起,任何未被错误边界捕获的错误将会导致整个 React 组件树被卸载。
如果遇到网络问题或是组件内部错误,页面的动态资源可能会加载失败,为了优雅降级展示降级 ui,可以使用 ErrorBoundaries 来解决这个问题。
如果一个 class 组件中定义了 static getDerivedStateFromError()
或 componentDidCatch()
这两个生命周期方法中的任意一个(或两个)时,那么它就变成一个错误边界 Error Boundaries 组件。
然后你可以将它作为一个常规组件去使用:
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
4、总结
React.lazy() 与 React.Suspense 的提出为现代 React 性能优化提供了便捷。React.lazy 可以让我们像渲染常规组件一样处理动态引入组件,结合 Suspense 可以更优雅地展示组件懒加载的过渡动画以及处理加载异常的场景。