React 应用程序中的代码分割
介绍
开发相对复杂的单页应用时,最大的问题之一是需要通过 Web 浏览器下载的代码包的大小。即使代码被最小化并压缩,它通常也会大于建议的最大文件大小,以提供良好的用户体验,而不会让用户看到空白窗口,甚至更糟的是,决定访问其他网站。
除了简单地编写更少的代码之外,代码拆分还是一种有用的技术,可以减少初始下载的大小并保持用户的参与度。本指南将展示如何构建 React 组件,使您能够使用 React 16.8 及更高版本中的高阶组件模式和 Suspense 拆分组件和包,以及如何在组件之外使用代码拆分。
动态导入
导入组件
实现代码分割最明显的方法是在组件级别动态导入。但这并不意味着每个组件都应该动态导入。相反,那些使用大型包(未在其他地方使用)的组件将是一个不错的选择。此外,在使用路由时,动态导入每个页面(主页除外)也是一个好主意。
要动态导入组件,您可以使用高阶组件模式的变体。高阶组件接受组件作为参数并返回组件。在这种情况下,您将接受解析为组件并返回组件的 Promise。此高阶组件可以定义一个状态变量来包含初始化为null 的渲染组件,如下所示:
this.state = { Component: null };
然后在高阶组件构造函数中,可以执行作为参数传递的 promise,并且当它解析时,可以使用生成的组件更新状态:
componentImport().then(loaded => this.setState({ Component: loaded.default }));
高阶组件中剩下要做的就是实现render生命周期方法。在这个方法中,我们可以测试状态是否为null来检查组件是否已加载。如果尚未加载,我们可以返回null或其他内容来通知用户应用程序正在等待。如果已加载,我们可以渲染传入 props 的组件。最终的高阶组件将如下所示:
function DynamicComponent(componentImport) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = { Component: null };
componentImport()
.then(loaded => this.setState({ Component: loaded.default }));
}
render() {
if (this.state.Component === null) {
return <div>Loading component, please wait</div>;
}
return <this.state.Component {...this.props} />;
}
};
}
我们使用import()函数作为参数来使用这个高阶组件,然后像这样呈现结果组件:
const DynamicImportComponent = DynamicComponent(() => import("./ShowUtc"));
return <DynamicImportComponent />;
使用 Suspense 导入
在 React 16.8 版中,引入了 Suspense API 的第一部分,它增加了使用lazy函数动态导入组件的功能。这与上面的高阶组件的工作方式类似。但是,在等待组件加载期间渲染的任何内容都使用其fallback属性定义为Suspense父组件的一部分。因此,要执行与上面的高阶组件相同的操作,您需要执行以下操作:
const LazyComponent = lazy(() => import("./ShowUtc"));
return (
<Suspense fallback={<div>Loading component, please wait</div>}>
<LazyComponent />
</Suspense>);
Suspense组件不必是使用lazy创建的组件的直接父组件。React 将返回组件树以查找Suspense的第一个实例并使用它。如果使用lazy渲染的组件在树中的任何位置都没有Suspense组件作为父组件,则 React 将抛出错误。
动态导入功能
上面的两个示例处理组件级别的动态导入,这在 React 应用程序中通常是必需的。但是,如果你在很少使用的函数中使用特别大的模块,则可能需要从函数内部动态导入该模块,以便仅在调用该函数时下载模块的代码。这也可以使用 import ()函数来完成,但不是使用组件状态来存储模块,而是可以使用模块将函数设为承诺,然后只需等待承诺的结果并使用它。例如,此函数导入 moment包并在加载后使用它:
async function getUtcData() {
const moment = (await import("moment")).default;
return {
utc: moment()
.utc()
.format(),
offset: moment().utcOffset(),
};
}
该函数的使用方式如下:
const { utc, offset } = await getUtcData();
结论
代码分割可以显著缩短单页应用程序的加载时间,因为只需在需要时从服务器下载代码即可。本指南展示了 React 和 Javascript 提供的模式和 API 来为开发人员简化这一过程。可在此处找到使用本指南中每种技术的示例应用程序。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~