代码拆分akaReact中的延迟加载

Code organization is important for the maintainability, scalability, and efficiency of a program. For example, a web application can be organized using links which lead to individual pages that separate how information and functionality is served to the user. In React, code is organized into their own components, and those components can be rendered specifically and intentionally on particular events, such as visiting a specific route or url path. An example is visiting the “home page/aboutme” url, which would trigger the rendering of a component that is responsible for loading the about me page.

代码组织对于程序的可维护性,可伸缩性和效率很重要。 例如,可以使用链接来组织Web应用程序,这些链接会导致各个页面,这些页面将如何向用户提供信息和功能分开。 在React中,代码被组织成它们自己的组件,并且可以在特定事件(例如访问特定的路由或url路径)上有针对性地专门呈现那些组件。 一个示例是访问“主页/ aboutme” URL,这将触发呈现负责加载“关于我”页面的组件的呈现。

As a program grows in complexity, more of this separation of code can be used to maintain organization. However, as a program becomes larger it also creates problems with efficiency. This is because, by default, an application is served in its entirety via the bundle.js file which stores all the code of the application in a condensed and optimized form. A large enough application can become inefficient when loading, especially if there are parts that are not utilized by the user (a user does not visit a certain page or use a certain feature of an application). In this context, loading those parts of the application is not efficient. This is when a technique known as code splitting, also known as lazy loading, can be useful.

随着程序复杂性的提高,可以使用更多这种代码分离来维护组织。 但是,随着程序的增大,它也会带来效率方面的问题。 这是因为,默认情况下,将通过bundle.js文件为整个应用程序提供服务,该文件以精简和优化的形式存储应用程序的所有代码。 足够大的应用程序在加载时可能会变得效率低下,尤其是当某些部分未被用户使用时(用户不会访问某个页面或使用应用程序的某些功能)。 在这种情况下,加载应用程序的那些部分效率不高。 这就是所谓的代码拆分(也称为延迟加载)技术有用的时候。

Code splitting is a technique which allows individual components to be loaded via their own file, apart from the global bundle.js file, and only when they are being used. For example, only when a user actually visits the “home page/aboutme” url will the component responsible for that page, and all its potential child components, be loaded. This is done by splitting your application’s code into chunks or individual chunk.js files. Using this technique would minimize the application’s bundle.js file allowing for faster loading. And every other part of your application, would only be loaded upon use. Let’s take a look at how this is implemented.

代码拆分是一种技术,它允许通过全局(除了bundle.js文件之外)单独的组件来加载单个组件,并且仅在使用它们时才可以。 例如,仅当用户实际访问“主页/ aboutme” URL时,才会加载负责该页面的组件及其所有潜在子组件。 这是通过将应用程序的代码拆分为多个块或单独的chunk.js文件来完成的。 使用此技术将最小化应用程序的bundle.js文件,从而加快加载速度。 应用程序的所有其他部分都只会在使用时加载。 让我们看一下它是如何实现的。

I’ll break up the entire code for the function into parts to better grasp what is happening.

我将把该函数的整个代码分成几个部分,以更好地掌握正在发生的事情。

import React, { Component } from 'react';const asyncComponent = (importComponent) => {
return class extends Component {
}
};

First off we create a function, called asyncComponent, the name can be anything but essentially lazy loading a component is loading it asynchronously. This function receives an argument, a function represented as importComponent. Again, this argument name is used because it will represent a function that does exactly that, imports the actual component. The asyncComponent function also returns a higher order component, or a component that wraps another component (in this case, the actual component that needs to be rendered) and does some process to it before returning it. The higher order component is an anonymous class component, and it is anonymous because its only responsibility is to potentially render the actual component that is needed.

首先,我们创建一个名为asyncComponent的函数,名称可以是任何东西,但本质上是延迟加载组件是异步加载它。 该函数接收一个参数,该函数表示为importComponent。 同样,使用此参数名称是因为它将代表一个函数,该函数将执行此操作,并导入实际组件。 asyncComponent函数还返回一个高阶组件,或者包装另一个组件的组件(在这种情况下,该组件是需要呈现的实际组件),并在返回之前对其进行一些处理。 高阶组件是一个匿名类组件,它是匿名的,因为它的唯一职责是潜在地呈现所需的实际组件。

import React, { Component } from 'react';const asyncComponent = (importComponent) => {
return class extends Component {
state = {
component: null
}
componentDidMount() {
importComponent().then(cmp => this.setState({
component: cmp.default
)};
);
}
}};

Afterwards, we add a state to the higher order component that will keep track of a potential component needing to be returned or rendered. Once the higher order component mounts, it will execute the function that is passed in as an argument to the asyncComponent function, importComponent. This function will return a promise (named “cmp” in this example) that will contain a property called default which will store the actual component that was imported by the execution of the importComponent function. Afterwards, the component needing to be rendered will be stored in state.

然后,我们向高阶组件添加一个状态,该状态将跟踪需要返回或呈现的潜在组件。 一旦安装了更高阶的组件,它将执行作为参数传递给asyncComponent函数importComponent的函数。 此函数将返回一个Promise(在此示例中为“ cmp”),该Promise将包含一个名为default的属性,该属性将存储由importComponent函数的执行导入的实际组件。 之后,需要渲染的组件将存储在状态中。

import React, { Component } from 'react';const asyncComponent = (importComponent) => {
return class extends Component {
state = {
component: null
}
componentDidMount() {
importComponent().then(cmp => this.setState({
component: cmp.default
)};
);
} render() {
const C = this.state.component; return C ? <C {...this.props}/> : null;
}
}};export default asyncComponent;

At this point, the component that is stored inside the promise is set to state. Then, inside the render method, the potential component defined inside the state, is assigned to the C variable, short for Component. And if there is an actual component set to state, then any props received by the higher order component is passed down to the actual component, otherwise null is returned.

此时,将存储在promise中的组件设置为state。 然后,在render方法内部,将状态内部定义的潜在组件分配给C变量,这是Component的缩写。 并且,如果有一个实际的组件设置为状态,那么高阶组件接收到的所有prop都将传递给该实际组件,否则返回null。

Now that the asyncComponent function is defined with its returning higher order component, it needs to be implemented. One example where it makes sense to implement this is when using Routes. So for example:

现在,已经使用返回的高阶组件定义了asyncComponent函数,需要对其进行实现。 当使用路由时,实现此目标的一个示例。 因此,例如:

* App.jsimport React from 'react';
import HomePage from './components/HomePage';
import AboutMe from './components/AboutMe';const App = () => {
return (
<div>
<Route path="/aboutme" component={AboutMe}/>
<Route path="/" component={HomePage}/>
</div>
);
}

In this example we have a standard way of loading certain components, particularly, the AboutMe component will render whenever you visit the “/aboutme” url. If a user does not visit this page, then including the code that handles this component, and all potential child components is not efficient.

在此示例中,我们有一种标准的方式来加载某些组件,特别是,当您访问“ / aboutme” URL时,AboutMe组件将呈现。 如果用户没有访问此页面,则包括处理该组件的代码,并且所有潜在的子组件都不有效。

So:

所以:

* App.jsimport React from 'react';
import HomePage from './components/HomePage';
import asyncComponent from './hoc/asyncComponent';const AsyncAboutMe = asyncComponent(() => import('./components/AboutMe'));const App = () => {
return (
<div>
<Route path="/aboutme" component={AsyncAboutMe}/>
<Route path="/" component={HomePage}/>
</div>
);
}

Now we no longer import the actual component directly, which would include its code into the global bundle.js file, instead we import the asyncComponent function that will execute an anonymous function (importComponent argument) that will import the component. By doing it this way, webpack creates an individual file for the component in the form of a chunk.js file which is loaded when needed. The function, importComponent, then executes the import function which dynamically imports the component. Finally, the route for “/aboutme” now points to the AsyncAboutMe variable which will either be null or contain the AboutMe component if the route is visited.

现在,我们不再直接导入实际组件,而是将其代码包含到全局bundle.js文件中,而是导入asyncComponent函数,该函数将执行将导入该组件的匿名函数(importComponent参数)。 通过这种方式,webpack会以chunk.js文件的形式为组件创建一个单独的文件,并在需要时加载。 函数importComponent然后执行import函数,该函数动态导入组件。 最后,“ / aboutme”的路由现在指向AsyncAboutMe变量,如果访问该路由,该变量将为null或包含AboutMe组件。

This all might seem very involved and so there is another approach to lazy loading which was later introduced, involving the lazy method on the React object. And it work like this:

这一切似乎都非常复杂,因此后来引入了另一种延迟加载方法,其中涉及React对象上的延迟方法。 它像这样工作:

* App.jsimport React, { Suspense } from 'react';
import HomePage from './components/HomePage';
const AboutMe = React.lazy(() => import('./components/AboutMe'));const App = () => {
return (
<div>
<Route path="/aboutme" render={() => {
return (
<Suspense fallback={someHTML}>
<AboutMe />
</Suspense>
);
}
}/>
<Route path="/" component={HomePage}/>
</div>
);
}

In this version, the lazy method substitutes the asyncComponent function receiving an anonymous function that invokes the import function. However, to use the asynchronously loaded component assigned to the AboutMe variable, we need to import the Suspense component which will wrap the actual AboutMe component. Also, the route to “/aboutme” utilizes the render method returning an anonymous function that returns the Suspense component with the actual component needing rendering as its child component. Also to note, the Suspense component takes a “fallback” prop which is used by React to render some HTML while the actual component is rendered. That HTML can be another component which is rendered first and immediately when the Suspense component is mounted, or it can be simply be some standalone HTML, for example a p tag with some text.

在此版本中,lazy方法替换asyncComponent函数,以接收调用导入函数的匿名函数。 但是,要使用分配给AboutMe变量的异步加载的组件,我们需要导入Suspense组件,该组件将包装实际的AboutMe组件。 同样,到“ / aboutme”的路由利用render方法返回一个匿名函数,该函数返回Suspense组件,并将需要渲染的实际组件作为其子组件。 还需要注意的是,Suspense组件采用了一个“ fallback”道具,React将该组件用于渲染实际组件时渲染一些HTML。 该HTML可以是挂起Suspense组件时首先显示并立即呈现的另一个组件,也可以只是一些独立HTML,例如带有一些文本的ap标签。

With this, you can now split your code into portions allowing for greater efficiency. And to see your asynchronous component loading in action, you can take a look in the developer tools under the “Network” tab, and when loading a component asynchronously, (visiting a page that is loaded using code splitting) you can see that a chunk.js file will appear which will contain the code for the loaded component. You can also read more on this in the React docs.

这样,您现在可以将代码分成多个部分,以提高效率。 要查看异步组件的运行情况,您可以在“网络”标签下的开发人员工具中查看,并且在异步加载组件时(访问通过代码拆分加载的页面),您可以看到.js文件将出现,其中将包含已加载组件的代码。 您还可以在React文档中阅读更多内容。

https://reactjs.org/docs/code-splitting.html

https://reactjs.org/docs/code-splitting.html

翻译自: https://medium.com/@codenameuriel28/code-splitting-aka-lazy-loading-in-react-6121d12bb42b

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值