Better

Ethan的博客,欢迎访问交流

React 如何实现模块的按需加载

突然发现已经有一个月没有输出内容了,公司最近这段时间确实也有点忙,与此同时自己也有点小焦虑,什么都想学,却好像给自己安排的太多了。六月份还是不要空白了,抓住小尾巴,写点笔记吧。

基础 API

React.lazy + 动态 import + Suspense

dynamic import

动态 import 实现按需加载的原理:由于打包工具的支持,比如 webpack 在遇到 import 语句时,就会从这个模块为起点,将其自身和下面的依赖单独打包成一个资源包,当浏览器执行的时候,遇到 import 这个点,就会去动态的加载对应的资源包,从而实现按需加载

import 语句返回的是一个 promise,当 promise 被 resolve 的时候表示加载完成了,参数就是模块本身,当加载失败则 reject

React.lazy

React.lazy 将一个需要动态加载的组件,封装成一个临时组件,在代码中使用这个临时组件时,就和标准的 React 组件完全一样。临时组件包含了加载中、加载完成两个状态

React.lazy 其实只要传入的参数返回一个 Promise,拿到这个 Promise 之后,React.lazy 会以抛出异常的方式抛出这个 Promise,外层的 Suspense 会捕获这个异常,并等待 Promise 的完成

手动实现一个 lazy 函数

let ComponentModule;
function MockLazy() {
    if(ComponentModule) {
        return <ComponentModule.default />
    }
    throw new Promise(resolve => {
        ComponentModule = { default: () => <div>Hello</div> }
        setTimeout(() => resolve(ComponentModule), 1000)
    })
}

Suspense

Suspense 表示组件的渲染过程暂时被挂起,等待某个异步事件完成之后才继续渲染,等待期间使用 fallback 提供的内容暂时渲染

Suspense 判断组件是否准备好的机制是通过捕获异常,其子组件只要任何一个抛出 Promise 作为异常,那么就只会渲染 fallback 提供的内容

在当前的 React 版本中,Suspense 只提供了和 lazy 一起使用的能力。任何使用 lazy 封装过的组件都必须放在 Suspense 中,否则编译时就会报错

在未来的 React 版本中,Suspense 还将提供并发渲染、数据获取等异步过程的渲染支持

如果模块加载失败,该如何处理呢。使用 ErrorBoundary,用来捕获子组件抛出的异常,从而显示一条错误信息。这对于 Suspense 同样是适用的。直接使用 ErrorBoundary 包裹 Suspense 组件即可



留言