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>
相关推荐
weixin_382395233 小时前
为小工厂量身打造:本地部署的物料管理系统带缺料计算
前端·制造
__zRainy__3 小时前
解决pnpm v10+不自动构建
前端·pnpm·工程化
猫猫不是喵喵.4 小时前
Vue3 Props 属性
前端·javascript·vue.js
醉城夜风~5 小时前
CSS元素显示模式(display)
前端·css
AI大模型-小华6 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子8 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅8 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni8 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学10 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端