React 的代码分割与懒加载
通过 React.lazy
和 Suspense
实现动态加载组件,可以有效减少初始加载时间,提高页面的首屏性能。代码分割的核心思想是将大文件拆分为多个小文件,按需加载,从而避免一次性加载过多内容。
示例场景
假设有一个应用包含以下三个页面组件:
- HomePage(主页)
- AboutPage(关于页)
- ContactPage(联系我们)
我们使用代码分割和懒加载实现按需加载页面组件。
代码示例
1. 项目结构
src/
components/
HomePage.tsx
AboutPage.tsx
ContactPage.tsx
App.tsx
index.tsx
2. 各页面组件
HomePage.tsx
import React from "react";
const HomePage = () => {
return <h1>欢迎来到主页</h1>;
};
export default HomePage;
AboutPage.tsx
import React from "react";
const AboutPage = () => {
return <h1>这是关于页面</h1>;
};
export default AboutPage;
ContactPage.tsx
import React from "react";
const ContactPage = () => {
return <h1>联系我们页面</h1>;
};
export default ContactPage;
3. 主应用组件 App.tsx
在 App.tsx
中使用 React.lazy
和 Suspense
来实现代码分割和懒加载。
import React, { Suspense, lazy, useState } from "react";
// 动态加载组件
const HomePage = lazy(() => import("./components/HomePage"));
const AboutPage = lazy(() => import("./components/AboutPage"));
const ContactPage = lazy(() => import("./components/ContactPage"));
const App = () => {
const [currentPage, setCurrentPage] = useState<string>("home");
// 根据当前页面选择显示的组件
const renderPage = () => {
switch (currentPage) {
case "home":
return <HomePage />;
case "about":
return <AboutPage />;
case "contact":
return <ContactPage />;
default:
return <HomePage />;
}
};
return (
<div>
<nav>
<button onClick={() => setCurrentPage("home")}>主页</button>
<button onClick={() => setCurrentPage("about")}>关于</button>
<button onClick={() => setCurrentPage("contact")}>联系我们</button>
</nav>
{/* Suspense 包裹懒加载的组件,设置加载中的 fallback */}
<Suspense fallback={<div>加载中...</div>}>
{renderPage()}
</Suspense>
</div>
);
};
export default App;
关键点解释
React.lazy
:- 用于动态加载组件。
- 调用时返回一个
Promise
,加载完成后返回组件。
const HomePage = lazy(() => import("./components/HomePage"));
Suspense
:- 用于包裹懒加载的组件,必须设置一个
fallback
属性,表示加载期间的占位内容。
- 用于包裹懒加载的组件,必须设置一个
<Suspense fallback={<div>加载中...</div>}>
<HomePage />
</Suspense>
- 按需加载:
React.lazy
会在用户真正访问到某个页面时,才加载对应的组件。- 这样可以减少初始加载的 JS 文件体积,从而优化页面首屏加载性能。
验证效果
- 初始加载:
- 打开应用时,只有主框架和当前页面的 JS 文件被加载。
- 切换页面:
- 当用户点击导航按钮时,React 会按需加载对应页面的组件文件。
- 性能提升:
- 通过开发者工具可以看到按需加载的 JS 文件大小和加载时机,从而验证性能优化效果。
注意事项
Suspense
的fallback
占位内容:- 可以设计为用户友好的加载动画或提示,而不是简单的文本。
- 错误处理:
- 如果懒加载的组件加载失败,可以使用
React Error Boundary
捕获错误并显示错误提示。
- 如果懒加载的组件加载失败,可以使用
- 搭配路由:
- 在实际项目中,通常会与路由库(如
react-router
)结合使用,实现页面切换时的动态加载。
- 在实际项目中,通常会与路由库(如
扩展示例:与 react-router
配合
如果你的项目使用 react-router
,可以结合 React.lazy
实现路由的代码分割:
import React, { Suspense, lazy } from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
const HomePage = lazy(() => import("./components/HomePage"));
const AboutPage = lazy(() => import("./components/AboutPage"));
const ContactPage = lazy(() => import("./components/ContactPage"));
const App = () => {
return (
<Router>
<Suspense fallback={<div>加载中...</div>}>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contact" element={<ContactPage />} />
</Routes>
</Suspense>
</Router>
);
};
export default App;
通过以上方法,初始加载只包含主框架的代码,页面组件会按需加载,从而进一步优化性能!