如何使用React Router 6的Lazy Loading(详细教程)

3,212 阅读3分钟

一个React Router教程,教你如何使用React Router 6的Lazy Loading。这个React Router v6教程的代码可以在这里找到。为了让你开始学习,请创建一个新的React项目(例如:create-react-app)。之后,安装React Router,并阅读下面的React Router教程,让自己与接下来的内容保持一致。

使用React Router在路由层面的懒惰加载是一个强大的功能。通常情况下,客户端渲染的React应用程序是来自Web服务器的一个捆绑包。然而,当启用懒惰加载时,该包被分割成更小的包。当用户访问应用程序的特定部分时,只有这部分会按需懒惰加载。这种优化的术语叫做代码拆分(Code Splitting),当用户浏览一个较大的React应用程序时,可以提高性能。

在下文中,我们将用React Router重现这个场景。为了说明这一点,以及在使用React Router在React中引入代码拆分时,你如何在路由层面实现懒惰加载,我们将从以下例子开始。

import * as React from 'react';
import { Routes, Route, Link } from 'react-router-dom';

import Home from './pages/Home';
import About from './pages/About';

const App = () => {
  return (
    <>
      <h1>React Router</h1>

      <nav>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
      </nav>

      <Routes>
        <Route index element={<Home />} />
        <Route path="about" element={<About />} />
        <Route path="*" element={<NoMatch />} />
      </Routes>
    </>
  );
};

const NoMatch = () => {
  return <p>There's nothing here: 404!</p>;
};

export default App;

在这个函数组件中,我们有来自React Router的匹配Link和Route组件,用于home/about/ 路由。此外,我们还有一个所谓的No Match Route,用NoMatch组件加载,作为回退路线。从这里开始,我们将探索Lazy Loading的概念。

React Router中的懒惰加载

主页和关于组件都是从另一个文件夹/文件中导入的。为了使这个例子更小,它们并没有做太多的事情。例如,主页组件可能看起来像下面这样。

const Home = () => {
  return (
    <>
      <h2>Home</h2>
    </>
  );
};

export default Home;

在React中懒惰地加载一个组件并不困难,因为React为它提供了一个顶级的API,叫做React.lazy。因为我们已经从另一个文件中导入了这两个页面组件,所以我们可以在这里直接使用React的lazy() 方法作为包装器。

import * as React from 'react';
import { Routes, Route, Link } from 'react-router-dom';

const Home = React.lazy(() => import('./pages/Home'));
const About = React.lazy(() => import('./pages/About'));

const App = () => {
  return (
    <>
      ...

      <Routes>
        <Route
          index
          element={
            <React.Suspense fallback={<>...</>}>
              <Home />
            </React.Suspense>
          }
        />
        <Route
          path="about"
          element={
            <React.Suspense fallback={<>...</>}>
              <About />
            </React.Suspense>
          }
        />
        <Route path="*" element={<NoMatch />} />
      </Routes>
    </>
  );
};

你可能已经注意到,我们在这里使用React Suspense来提供一个后备的React元素,当组件从服务器上懒散加载时。在这一点上,值得注意的是,懒惰加载并不是React Router特有的,而是React特有的,因为我们作为开发者选择在页面组件上应用React.lazy方法,在路由级别上实现懒惰加载。然而,任何组件都可以通过这种方式进行懒惰加载。

如果两个页面组件都被命名为export,而不是默认的export,那么只使用React.lazy的懒惰加载就变得很麻烦了。相反,我想向你展示一个流行的React的懒惰加载库,叫做@loadable/component。安装后,你可以这样使用它。

import * as React from 'react';
import { Routes, Route, Link } from 'react-router-dom';
import loadable from '@loadable/component';

const Home = loadable(() => import('./pages/Home'));
const About = loadable(() => import('./pages/About'));

const App = () => {
  return (
    <>
      ...

      <Routes>
        <Route index element={<Home />} />
        <Route path="about" element={<About />} />
        <Route path="*" element={<NoMatch />} />
      </Routes>
    </>
  );
};

看看这个库如何默认应用React Suspense。此外,如果你的页面组件刚好被命名为export,你可以用以下方式来懒惰加载它们:

const Home = loadable(() => import('./pages/Home'), {
  resolveComponent: (components) => components.Home,
});

const About = loadable(() => import('./pages/About'), {
  resolveComponent: (components) => components.About,
});

这就是了。我们通过使用React的懒惰功能,在路由层面引入了懒惰加载。此外,为了方便起见,我们引入了一个有助于的选择库。毕竟,在路由级别上使用应付拆分,可以提高大型React应用的性能,因为你的用户不必下载整个应用。相反,只有一个根加一个页面被加载。当用户导航到另一个页面时,这个页面会被懒惰地加载。