使用ReactLoadable在React中进行代码拆分
代码拆分是一种在现代 Web 应用程序开发中更多使用的技术,它允许仅在需要时加载代码块。 例如,使用基于路由的代码拆分,用户可以导航到应用程序的不同路由,并且在幕后,每个路由的代码仅在第一次访问时加载。 使用代码拆分,在应用程序初始化时只能加载最少量的代码,并按需加载额外的代码。 通过允许减小初始捆绑包大小,这可以极大地提高性能。
React Loadable 是 @jamiebuilds 的一个库,它可以很容易地在 React 中实现代码拆分,并且包含 React 的组件模型。 它使用 动态导入 实现它的魔力,并且 webpack 在捆绑时自动将动态导入拆分为单独的块。
让我们快速回顾一下如何使用 React Loadable。
安装
只需使用 npm 或 Yarn 将 react-loadable 包添加到您的项目中:
$ npm install react-loadable # or $ yarn add react-loadable
用法
让我们创建一个人为的例子来说明 Loadable 是多么简单。 首先,SomeComponent:
组件/SomeComponent.js
import React from 'react';
function SomeComponent() {
return <h1>Some Component! 💣🚀👨🎤🤘</h1>;
}
export default SomeComponent;
然后让我们在我们的 App 组件中使用它:
应用程序.js
import React, { Component, Fragment } from 'react';
import SomeComponent from './components/SomeComponent';
class App extends Component {
state = {
showComponent: false
};
handleClick = () => {
this.setState({
showComponent: true
});
};
render() {
if (this.state.showComponent) {
return <SomeComponent />;
} else {
return (
<Fragment>
<h1>Hello!</h1>
<button onClick={this.handleClick}>Click me!</button>
</Fragment>
);
}
}
}
export default App;
注意组件是如何仅在用户单击按钮后才呈现到视图中的。 显然,对于这样一个简单的组件,它并没有什么不同,但是对于一个应用程序中较大的组件,这是一个不平凡的,代码拆分该组件可能是一个好主意。
让我们使用 React Loadable 重构一下代码拆分:
应用程序.js
import React, { Component, Fragment } from 'react';
import Loadable from 'react-loadable';
function Loading() {
return <h3>Loading...</h3>;
}
const SomeComponent = Loadable({
loader: () => import('./components/SomeComponent'),
loading: Loading
});
class App extends Component {
state = {
showComponent: false
};
handleClick = () => {
this.setState({
showComponent: true
});
};
render() {
if (this.state.showComponent) {
return <SomeComponent />;
} else {
return (
<Fragment>
<h1>Hello!</h1>
<button onClick={this.handleClick}>Click me!</button>
</Fragment>
);
}
}
}
export default App;
Loadable 高阶组件采用具有两个键的对象:loader 和 loading:
- loader:期望一个函数返回一个解析为 React 组件的 Promise。 使用
import()的动态导入返回一个承诺,所以我们所要做的就是指向要加载的组件的位置。 - loading:期望在加载代码时呈现组件。
就这么简单! 如果您查看浏览器的 Devtools 中的 Network 选项卡,您会看到单击按钮时正在加载的块。
加载延迟
如果组件被快速加载,则具有中间加载组件可能会成为 UI 中视觉烦恼的来源。 幸运的是,Loadable 以 pastDelay 道具的形式提供了一种简单的解决方法,该道具被传递给加载组件,并且一旦经过一定的延迟就会评估为真:
// ...
function Loading({ pastDelay }) {
return pastDelay ? <h3>Loading...</h3> : null;
}
const SomeComponent = Loadable({
loader: () => import('./components/SomeComponent'),
loading: Loading
});
// ...
默认延迟为 200ms,但您可以通过将 delay 配置传递给可加载 HOC 来更改它。 例如,我们将最大延迟更改为 60 毫秒:
function Loading({ pastDelay }) {
return pastDelay ? <h3>Loading...</h3> : null;
}
const SomeComponent = Loadable({
loader: () => import('./components/SomeComponent'),
loading: Loading,
delay: 60
});
错误
另一个 prop 被传入加载组件,error,如果在尝试加载组件时发生错误,它可以很容易地渲染其他内容:
function Loading({ error }) {
if (error) {
return 'oh-noes!';
} else {
return <h3>Loading...</h3>;
}
}
const SomeComponent = Loadable({
loader: () => import('./components/SomeComponent'),
loading: Loading
});
基于路由的代码拆分
通常,对应用程序进行代码拆分的最简单方法是在路由级别。 由于使用 React Router v4 时 React 中的路由只是组件,因此使用 React Loadable 按需加载不同路由的代码同样容易。
在这里,我们将介绍一个使用 React Loadable 进行基于路由的代码拆分的简单示例。 首先,确保我们的项目中还有 react-router-dom 可用:
$ npm install react-router-dom # or $ yarn add react-router-dom
在以下示例中,我们静态导入 Dashboard 组件,因为它会在根路由上立即需要,我们使用 Loadable 仅加载 Settings 和 AddUser[X199X ] 组件,当它们各自的路由被激活时:
import React, { Component } from 'react';
import Loadable from 'react-loadable';
import { Link, Route, BrowserRouter as Router } from 'react-router-dom';
import Dashboard from './components/Dashboard';
function Loading({ error }) {
if (error) {
return 'Oh nooess!';
} else {
return <h3>Loading...</h3>;
}
}
const Settings = Loadable({
loader: () => import('./components/Settings'),
loading: Loading
});
const AddUser = Loadable({
loader: () => import('./components/AddUser'),
loading: Loading
});
class App extends Component {
render() {
return (
<Router>
<div>
<Link to="/">Dashboard</Link>
<Link to="/settings">Settings</Link>
<Link to="/add-user">Add User</Link>
<Route exact path="/" component={Dashboard} />
<Route path="/settings" component={Settings} />
<Route path="/add-user" component={AddUser} />
</div>
</Router>
);
}
}
export default App;
🏇 有了这个,你应该参加代码拆分的比赛! 查看 项目的自述文件 以深入了解 API 和有关高级主题(如服务器端渲染)的文档。