我如何使用 React.lazy 节省 100KB

2025-06-04

我如何使用 React.lazy 节省 100KB

这篇文章是关于如何将我的主页 JavaScript 减少约 100KB 的。

TL;DR:使用React.lazyReact.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.jsrender 又依赖于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.lazyAPI,我们可以实现惰性导入。像这样:

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
PREV
让我快速且高效的工具
NEXT
🌐 如何在子域名上托管我的项目