关于 React、Suspense、lazyLoad 和 preloading/rendering 元素

About React, Suspense, lazyLoad and preloading/rendering elements

我正在研究 <Suspense>React.lazy() 概念,我想更好地理解发生了什么,以便将一些逻辑添加到现有应用程序中。

让我们从定义开始:

The React.lazy function lets you render a dynamic import as a regular component.

(render 由我突出显示)

If the module containing the OtherComponent is not yet loaded by the time MyComponent renders, we must show some fallback content while we’re waiting for it to load[...]

(已加载 由我突出显示)

现在,Suspense 定义使用术语 loadlazy() 使用 render.

让我们为这个概念添加一些代码。

const ComponentOne = React.lazy(() => import("./ComponentOne"));
const ComponentTwo = React.lazy(() => import("./ComponentTwo"));

function BigBang() {
    return (
        <Suspense fallback={<SplashScreen/>}>
            <section>
                <ComponentOne/>
                <ComponentTwo/>
            </section>
        </Suspense>
    );
}

很好。我们的想法是延迟加载 ComponentOne 和 ComponentTwo。 虽然这个过程还没有结束,但我们将显示 SplashScreen。

问题 现在,假设我将一些本地图像导入到 ComponentOne 和 ComponentTwo 中(我将只为一个添加代码,假设另一个有类似的东西):

import avatar from "../../img/avatar.svg";
import logo from "../../img/logo.svg";

export default class ComponentOne extends React.Component {
    componentDidMount() {
        console.log("ComponentOne@componentDidMount");
    }

    render() {
        console.log("ComponentOne@render");
        return (
            <div style={{display: 'none'}}>
                <img src={avatar}/>
                <img src={logo}/>
            </div>
        );
    }
}

现在应该清楚我想问的是什么了:

加载所有导入后,SplashScreen 是否消失?换句话说,当SplashScreen消失时,我是否可以假设ComponentOne和ComponentTwo中的所有图像都已经加载?

这是主要问题。

第二个问题(这似乎与我有关,但如果不是我可以打开另一个线程)是:如果上一个问题的答案是 "NO",那么确定的最佳策略是什么images/fonts/"api response"/"other resources" 在渲染之前加载,可能因为已经存在的流而维护逻辑?目前不支持直接 fetch() 到资源。

Suspense 等待获取动态导入的组件文件(比方说 0.js)。 现在,一旦 0.js 加载并开始解析,Suspense 就会停止显示 SplashScreen 并委托控制您的组件。接下来发生的任何事情都不是延迟加载。就像您进行静态导入时会发生的情况一样。

在您的情况下,只有在 SplashScreen 消失后才会加载这两个图像。现在,如果你想预加载/延迟加载图像,有几种方法可以继续。

1) 如果你使用的是 webpack,你可以使用 url-loader 将图像内联为 data-uri。但请注意,这可能会增加您的包大小,并且您还会失去通常是静态的图像的浏览器缓存。

2) 对于 svg,您可以使用 inline-react-svg babel 插件,它将 svg 转换为 react 组件,使其成为您的包的一部分 (0.js)。但它也有上面提到的相同权衡。

因此预加载图像有其自身的权衡。可能有更好的选择,例如可以轻松完成的延迟加载,也可以从几个第三方库中获得 React HOC。