React 路由懒加载入门:提升首屏性能的第一步

React 中的路由懒加载入门:提升首屏性能的第一步

在现代前端开发中,React 应用的体积越来越大 ,尤其是随着功能的不断扩展,首屏加载时间也随之增加。为了优化用户体验和提高应用性能,路由懒加载(Lazy Loading Routes) 成为了一种非常重要的技术手段。

本文将带你深入了解如何在 React 项目中实现路由懒加载,并结合 React.lazySuspenseReact Router 实现高效的代码分割与按需加载。

一、什么是路由懒加载?

路由懒加载指的是在用户访问某个路由时,才动态加载对应的组件资源。这种方式可以避免一次性加载整个应用的所有代码,而是根据需要分块加载,从而显著减少初始加载时间。

  • 没有使用路由懒加载的情况

    根组件组件

    jsx 复制代码
    import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
    import Home from './pages/Home'
    import About from './pages/About'
    import Login from './pages/Login'
    import Navigation from './components/Navigation'
    import './App.css'
    
    function App() {
    
      return (
        <>
          <Router>
            <Navigation />
            <Routes>
              <Route path="/" element={<Home />} />
              <Route path="/about" element={<About />} />
              <Route path="/login" element={<Login />} />
            </Routes>
          </Router>
        </>
      )
    }
    export default App

    Home组件

    jsx 复制代码
    console.log('加载Home组件')
    export default function Home() {
      console.log('Home')
      return (
        <div>
          <h1>Home</h1>
          <p>这是Home页面</p>
        </div>
      );
    }

    About组件

    jsx 复制代码
    console.log('加载About组件')
    export default function About() {
      console.log("About组件");
      return (
        <div>
          <h1>About</h1>
          <p>这是About页面</p>
        </div>
      );
    }

    Login组件

    jsx 复制代码
    console.log('加载Login组件')
    export default function Login() {
      console.log('Login')
      return (
        <div>
          <h1>登录</h1>
        </div>
      );
    }

    输出情况

    复制代码
    加载Home组件
    加载About组件
    加载Login组件
    Home

    这是因为当使用import导入组件时,浏览器或打包工具(如 Webpack、Vite)会加载并执行整个 .jxs 文件(不会执行组件函数)。所以这些组件都加载并执行了,若应用中存在多个路由页面时,如果所有组件都在首页一次性加载,会导致页面加载速度变慢,影响用户体验。

  • 使用路由懒加载的情况

    jsx 复制代码
    import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
    import Navigation from "./components/Navigation";
    import "./App.css";
    import { lazy, Suspense } from "react";
    
    function App() {
      const Home = lazy(() => import("./pages/Home"));
      const About = lazy(() => import("./pages/About"));
      const Login = lazy(() => import("./pages/Login"));
      return (
        <>
          <Router>
            <Navigation />
            <Suspense fallback={<div>Loading...</div>}>
              <Routes>
                <Route path="/" element={<Home />} />
                <Route path="/about" element={<About />} />
                <Route path="/login" element={<Login />} />
              </Routes>
            </Suspense>
          </Router>
        </>
      );
    }
    export default App;

    输出情况

    复制代码
    加载Home组件
    Home

    从输出情况可以看出 除了Home组件加载了,其他组件都没有加载

二、React 中实现懒加载的核心 API

  1. React.lazy

    React.lazy 是 React 提供的一个用于延迟加载组件的函数。它介绍一个函数作为参数,这个函数返回import()动态导入。lazy返回的是一个特殊的 React 组件,这个组件在首次渲染时才会真正加载。

    jsx 复制代码
    import { lazy } from "react";
    const Home = lazy(() => import('./Home'));
  2. <Suspense>

    由于懒加载组件是异步加载的,在加载完成之前,我们需要显示一个"加载中"的状态 ,为用户提供良好的体验。<Suspense> 就是用来包裹这些懒加载组件并提供加载状态的组件。

    jsx 复制代码
    import React, { Suspense } from 'react';
    
    function App() {
      return (
        <Suspense fallback="Loading...">
          <Home />
        </Suspense>
      );
    }
  3. 执行逻辑

    首次渲染 时React 会执行 () => import('./Home'),然后开始异步加载 Home 的代码,在加载期间显示 <Suspense>fallback UI。加载完成后 动态导入的组件会替换这个占位组件并渲染实际的 SomeComponent

三、在 React Router 中实现路由懒加载

如果你使用的是 React Router v6+ ,可以通过组合 React.lazy + Suspense 来实现懒加载路由。

示例:基本结构

jsx 复制代码
import React, { Suspense } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

// 懒加载页面组件
const Home = React.lazy(() => import('./pages/Home'));
const About = React.lazy(() => import('./pages/About'));
const Contact = React.lazy(() => import('./pages/Contact'));

function App() {
  return (
    <Router>
      <Suspense fallback="Loading...">
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/contact" element={<Contact />} />
        </Routes>
      </Suspense>
    </Router>
  );
}

export default App;

这样,每个页面组件都会在用户访问对应路径时才加载,而不是一开始就全部加载。

四、增强体验:添加加载状态与错误处理

  1. 自定义加载组件

    你可以自定义一个通用的加载提示组件:

    jsx 复制代码
    function Loading() {
      return <div className="loading">加载中,请稍候...</div>;
    }

    然后在 Suspense 中使用:

    jsx 复制代码
    <Suspense fallback={<Loading />}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Suspense>
  2. 错误边界(Error Boundary)

    懒加载过程中可能会出现网络问题或其他错误,建议使用错误边界来捕获异常,避免页面崩溃。

    jsx 复制代码
    class ErrorBoundary extends React.Component {
      state = { hasError: false };
    
      static getDerivedStateFromError(error) {
        return { hasError: true };
      }
    
      render() {
        if (this.state.hasError) {
          return <div>页面加载出错,请刷新重试。</div>;
        }
        return this.props.children;
      }
    }

    结合使用:

    jsx 复制代码
    <ErrorBoundary>
      <Suspense fallback={<Loading />}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </Suspense>
    </ErrorBoundary>
相关推荐
brzhang5 小时前
我操,终于有人把 AI 大佬们 PUA 程序员的套路给讲明白了!
前端·后端·架构
止观止6 小时前
React虚拟DOM的进化之路
前端·react.js·前端框架·reactjs·react
goms6 小时前
前端项目集成lint-staged
前端·vue·lint-staged
谢尔登6 小时前
【React Natve】NetworkError 和 TouchableOpacity 组件
前端·react.js·前端框架
Lin Hsüeh-ch'in6 小时前
如何彻底禁用 Chrome 自动更新
前端·chrome
augenstern4168 小时前
HTML面试题
前端·html
张可8 小时前
一个KMP/CMP项目的组织结构和集成方式
android·前端·kotlin
谢尔登9 小时前
【React Native】ScrollView 和 FlatList 组件
javascript·react native·react.js
蓝婷儿9 小时前
每天一个前端小知识 Day 27 - WebGL / WebGPU 数据可视化引擎设计与实践
前端·信息可视化·webgl