我如何使用 React.lazy 节省 100KB
这篇文章是关于如何将我的主页 JavaScript 减少约 100KB 的。
TL;DR:使用React.lazy
和React.Suspense
延迟加载非关键依赖项
我有一个从create-react-app启动的 React 应用。该应用中的一个页面(只是一个 React 组件)使用了CodeMirror(一个代码编辑器)。该应用使用react-router进行路由。因此,这个页面组件和所有其他页面一样,被导入到主App
组件中,并提供给路由器。
App.js
import Home from "./Home";
import Page2 from "./Page2";
function App() {
<Router>
<Route path="/" component={Home} />
<Route path="/page2" component={Page2} />
</Router>;
}
Page2.js
import CodeMirror from "react-codemirror";
function App() {
return (
<div>
<CodeMirror />
</div>
);
}
注意:react-codemirror
实际上执行的是命名导出。但为了简单起见,我假设是默认导出。
这种情况会导致Page2.js
对 render 产生同步依赖App.js
。而Page2.js
render 又依赖于react-codemirror
。因此,间接地,react-codemirror
成为对 render 的同步依赖App.js
。这基本上意味着我们访问的任何页面,react-codemirror
都会在页面渲染之前被获取和解析。即使该页面甚至没有使用 Codemirror!让我们解决这个问题。
解决方案
解决方案非常简单明了。React 最近引入了一个新的 API:React.lazy
。以及一个名为 的配套组件Suspense
。以下是我们使用它们来解决问题的方法。
步骤 1:使导入变得懒惰
Page2.js
导入react-codemirror
。理想情况下,我们希望在实际访问 Page2 时异步Page2.js
加载。react-codemirror
这是我们目前的Page2.js
:
import CodeMirror from "react-codemirror";
function App() {
return (
<div>
<CodeMirror />
</div>
);
}
使用React.lazy
API,我们可以实现惰性导入。像这样:
import React from "react";
const CodeMirror = React.lazy(() => import("react-codemirror"));
function App() {
return (
<div>
<CodeMirror />
</div>
);
}
这开箱即用!无需对CodeMirror
组件的使用方式进行任何更改。现在您会注意到,最初当您在主页时,CodeMirror 不会加载。当您访问/page2/时,您会在 CodeMirror 异步加载期间短暂地看到原本要渲染的区域为空白。加载完成后,CodeMirror
组件便会渲染。
在获取 CodeMirror 时,CodeMirror 编辑器应该出现的位置却变成了空白。这体验很差,因为用户无法获得关于该空白区域的任何信息。这时,React.Suspense
组件就派上用场了。
步骤2:改善空白环境
为了改善体验,我们需要做以下事情:
import React, { Suspense } from "react";
const CodeMirror = React.lazy(() => import("react-codemirror"));
function App() {
return (
<div>
<Suspense fallback="Loading editor...">
<CodeMirror />
</Suspense>
</div>
);
}
我们用一个标签包裹异步/惰性组件Suspense
,并赋予它一个fallback
应该显示的空格。就这样!
额外提示
使用时有一个特殊要求React.lazy
需要注意。它仅适用于具有默认导出的组件。因此,具有命名导出的组件无法使用它进行延迟导入。但是你可能拥有具有命名导出的组件,那么该怎么办?这里有一个小技巧。假设我们的Page2.js
文件导出了Page2
组件,因此它最初被导入为import {CodeMirror} from 'react-codemirror'
。在这种情况下,我们可以React.lazy
按如下方式使用它:
import React, { Suspense } from "react";
const CodeMirror = lazy(() =>
import("react-codemirror").then(module => ({ default: module.CodeMirror }))
);
function App() {
return (
<div>
<Suspense fallback="Loading editor...">
<CodeMirror />
</Suspense>
</div>
);
}
我们在这里所做的是,一旦我们导入了命名模块,then
我们就会在回调内部将其变成一个看似默认的导出模块 - 一个在键上可用模块的对象default
。
附注:这个应用程序是CSSBattle。
好了,各位!去精简一下页面中不必要的字节吧。如果您有任何问题或意见,请在这里或 Twitter 上@chinchang457问我(欢迎私信)。
文章来源:https://dev.to/chinchang/how-i-saved-100kb-with-react-lazy-59gm