如何使用React.lazy和Suspense进行组件延迟加载

by Boris Sever

通过鲍里斯·塞弗(Boris Sever)

如何使用React.lazy和Suspense进行组件延迟加载 (How to use React.lazy and Suspense for components lazy loading)

React 16.6 brought code-splitting to a new level. You can now load your components when it’s really needed without installing additional libraries.

React 16.6将代码拆分提升到一个新的水平。 现在,您可以在真正需要时加载组件,而无需安装其他库。

什么是代码拆分和延迟加载? (What are code-splitting and lazy loading?)

Webpack defines code-splitting as:

Webpack将代码拆分定义为:

“technique of splitting your code into various bundles which can then be loaded on demand or in parallel”. [Source]

“将您的代码分成各种捆绑包,然后可以按需或并行加载的技术”。 [ 来源 ]

Another way to say: “loading on demand or in parallel” is lazy-loading.Opposite of lazy-loading is eager-loading. Here everything is loaded no matter if you use it or not.

另一种说法是:“按需加载或并行加载 ”是延迟加载 。延迟加载的对立面是快速加载 。 无论是否使用,这里都会加载所有内容。

为什么我们要使用代码拆分和延迟加载? (Why would we use code-splitting and lazy loading?)

Sometimes we have to introduce a big chunk of code to cover some functionality. This code can be importing 3rd party dependency or writing it on our own. This code then affects the main bundle’s size.

有时我们必须引入一大堆代码来覆盖某些功能。 此代码可以导入第三方依赖关系,也可以自己编写。 然后,此代码会影响主捆绑包的大小。

Downloading a few MBs is a piece of cake for today’s internet speed. We still have to think about the users with a slow internet connection or using mobile data.

对于当今的互联网速度而言,下载几MB只是小菜一碟。 我们仍然必须考虑互联网连接速度慢或使用移动数据的用户。

在React 16.6之前是如何完成的? (How was it done before React 16.6?)

Probably the most popular library for lazy loading of React components is react-loadable.

延迟加载React组件最流行的库可能是react-loadable .

It’s important that reactjs.org still recommends react-loadable if your app is rendered on the server. [Source]

重要的是,如果您的应用程序在服务器上呈现,则reactjs.org仍然建议react-loadable 。 [ 来源 ]

react-loadable is actually pretty similar to the new approach by React. I will show this in the following demo.

实际上, react-loadable与React的新方法非常相似。 我将在以下演示中对此进行展示。

设置需要什么吗? (Is anything needed for setup?)

Let's see what reactjs.org has to say about it:

让我们看看reactjs.org对此有何评论:

“If you’re using Create React App, Next.js, Gatsby, or a similar tool, you will have a Webpack setup out of the box to bundle your app.

“如果您使用的是Create React AppNext.jsGatsby或类似的工具,则将有一个开箱即用的Webpack设置来捆绑您的应用程序。

If you aren’t, you’ll need to setup bundling yourself. For example, see the Installation and Getting Started guides on the Webpack docs.“

如果不是,则需要设置捆绑自己。 例如,请参阅Webpack文档上的“ 安装入门指南 ”。”

Ok, so Webpack is required, which handles dynamic imports of the bundles.

好的,因此需要Webpack ,它可以处理捆绑包的动态导入。

The following demo is generated using Create React App. And in that case, Webpack is already configured and we’re ready to go.

以下演示是使用Create React App.生成的Create React App. 在这种情况下, Webpack已经配置好了,我们就可以开始了。

演示 (DEMO)

For this demo, we will use react-pdf. react-pdf is an awesome library used for creating PDF files on the browser, mobile, and server. We could generate a PDF on the server, but if we would rather do it on the client side, it comes with a cost: bundle size.

对于此演示,我们将使用react-pdfreact-pdf是一个很棒的库,用于在浏览器,移动设备和服务器上创建PDF文件。 我们可以在服务器上生成PDF,但是如果我们希望在客户端上生成PDF,则需要付出一定的代价:包大小。

I’m using Import cost extension for Visual Studio Code to see the sizes of the libraries used.

我正在使用Visual Studio Code的Import cost extension来查看所用库的大小。

Let's say our requirement is to generate a PDF file when a user clicks on the button.

假设我们的要求是当用户单击按钮时生成PDF文件。

Now, this is a simple form with only one use case. Try to imagine a huge web app where this is a fraction of possibilities. Maybe this functionality is not used very often by the users.

现在,这是一种只有一个用例的简单形式。 尝试想象一个巨大的Web应用程序,其中可能性很小。 也许用户很少使用此功能。

Let’s put ourselves into that situation. PDF generation isn’t used very often and it doesn’t make sense to load the whole code for every page request.

让我们进入那种情况。 PDF生成并不经常使用,并且对于每个页面请求都加载整个代码没有意义。

I’ll try to show how we can develop a solution with lazy loading and without it.

我将尝试展示如何开发一个有延迟加载和没有延迟加载的解决方案。

渴望VS延迟加载展示 (Eager VS lazy loading showcase)

For both cases, we will use one component which imports dependencies from react-pdf and renders a simple PDF document.

对于这两种情况,我们都将使用一个组件来从react-pdf导入依赖react-pdf并呈现一个简单的PDF文档。

Nothing spectacular going on here. We importPDFViewer, Document, Page, Text, View from react-pdf. These are all used in render method of PDFPreview component.

这里没有什么壮观的事情。 我们从react-pdf导入PDFViewerDocumentPageTextView 。 这些全部用于PDFPreview组件的render方法中。

PDFPreview receives only one prop called title. As the name implies, it is used as a title in a newly generated PDF file.

PDFPreview仅接收一个称为title prop 。 顾名思义,它在新生成的PDF文件中用作标题。

pdfStyles.js looks like this:

pdfStyles.js看起来像这样:

渴望加载 (Eager loading)

Let’s first see how the parent component without lazy loading could look like:

首先让我们看一下没有延迟加载的父组件的样子:

which renders the following view in the browser:

在浏览器中呈现以下视图:

Let's go through the code together:

让我们一起看一下代码:

On line 2 we import PDFPreview component.

在第2行,我们导入PDFPreview组件。

On line 6 we initialize the state with default values. name is a field used as a title in the PDF file, while field PDFPreview is a boolean which shows or hides PDFPreview.

在第6行,我们使用默认值初始化状态。 name是一个字段,用作PDF文件中的标题,而PDFPreview字段是显示或隐藏PDFPreview的布尔值。

Now, let's jump to render method and check what will be rendered.

现在,让我们跳到render方法并检查将要渲染的内容。

On line 19 and 25 we render an input and a button. When user types into the input, name in the state is changed.

在第19和25行,我们渲染一个输入和一个按钮。 当用户键入输入时,状态中的name会更改。

Then when a user clicks on the “Generate PDF ”, showPDFPreview is set to true. The component re-renders and shows thePDFPreview component.

然后,当用户单击“ Generate PDF”时, showPDFPreview设置为true 。 该组件将重新渲染并显示PDFPreview组件。

Even though we use PDFPreview only on user click, all code related to it is included in the app bundle:

即使我们仅在用户单击时使用PDFPreview ,但与之相关的所有代码都包含在应用程序捆绑包中:

This is a development environment. In production, the sizes would be significantly smaller. Still, we’re not splitting the code optimally.

这是一个开发环境。 在生产中,尺寸将明显较小。 尽管如此,我们仍未以最佳方式拆分代码。

延迟加载 (Lazy loading)

We’ve only made small changes and let's go through them.

我们仅作了一些小改动,让我们进行研究。

Line 2 is replaced with: const LazyPDFDocument = React.lazy(() => import("./PDFPreview"));

第2行替换为: const LazyPDFDocument = React.lazy(() => import("./PDFPreview" ));

Let's see what the React docs say about React.lazy:

让我们看看React文档对React.lazy的评价:

React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component.

React.lazy 采用了必须调用动态import()的函数。 这必须返回一个Promise ,该Promise解析为一个带有default导出的模块,该模块包含一个React组件。

React.lazy takes a function that must call a dynamic import(). This must return a Promise which resolves to a module with a default export containing a React component. - reactjs.org

React.lazy 采用了必须调用动态import()的函数。 这必须返回一个Promise ,该Promise解析为一个带有default导出的模块,该模块包含一个React组件。 -reactjs.org

On line 27 we use Suspense, which must be a parent of a lazy-loaded component. When showPDFPreview is set to true, LazyPDFDocument is starting to load.

在第27行,我们使用Suspense ,它必须是延迟加载的组件的父代。 当showPDFPreview设置为true时, LazyPDFDocument开始加载。

Until the child component is resolved, Suspense shows whatever is provided to fallback prop.

在子组件解析之前, Suspense显示为fallback道具提供的所有内容。

The end result looks like this:

最终结果如下所示:

We can see 0.chunk.js weights significantly less than before and 4.chunk.js and 3.chunk.js are loaded on button press.

我们可以看到0.chunk.js的权重明显小于之前,并且在按按钮时加载了4.chunk.js3.chunk.js

结论 (Conclusion)

Every time we are introducing a new dependency into our project, our responsibility is to evaluate its cost and check how it affects the main bundle.

每次我们在项目中引入新的依赖项时,我们的责任就是评估其成本并检查其如何影响主捆绑包。

Then we have to ask is this functionality going to be used rarely and can we load it on demand without sacrificing the user experience.

然后我们要问的是,该功能将很少使用,是否可以在不牺牲用户体验的情况下按需加载它。

If the answer is yes, then React.Lazy and Suspense really help us with that task.

如果答案是肯定的,那么React.LazySuspense确实可以帮助我们完成该任务。

Thank you for reading! Please share it with anyone who might find it useful and leave feedback.

感谢您的阅读! 请与可能有用的任何人分享并留下反馈。

翻译自: https://www.freecodecamp.org/news/how-to-use-react-lazy-and-suspense-for-components-lazy-loading-8d420ecac58/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值