React 路由懒加载

865 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

一、路由懒加载

v16.6.0

  • Add React.lazy() for code splitting components. (@acdlite in #13885)

1、背景

随着前端应用体积的增大,资源加载的优化是我们必须要面对的一个问题,动态加载就是一种常用的解决方式。

在React16.6.0版本中,新增了React.lazy函数,它能让你像常规组件一样处理动态引入的组件,配合 webpack 的 Code Splitting,只有当组件被加载,对应的资源才会导入,从而达到懒加载的效果。

2、使用

// 使用懒加载
const OtherComponent = React.lazy(() => import('./OtherComponent'));

// 之前不使用懒加载
import OtherComponent from './OtherComponent';
  • 语法
  1. React.lazy 接受一个函数作为参数,这个函数需要调用import()。
  2. React.lazy 方法返回的是一个lazy组件的对象,类型是react.lazy,并且 lazy 组件具有 _status 属性。并且与 promise 类似,有 Pending,Resolved,Rejected 三个状态,分别代表组件的加载中,已加载、加载失败三个状态。
  • 注意
  1. 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 可以更优雅地展示组件懒加载的过渡动画以及处理加载异常的场景。