lazy / Suspense 与虚拟列表
约 385 字大约 1 分钟
布欧-Lewyon
2026-05-15
React.lazy + Suspense
代码分割,按需加载组件。
import { lazy, Suspense } from 'react'
// 懒加载组件
const Dashboard = lazy(() => import('./pages/Dashboard'))
const Settings = lazy(() => import('./pages/Settings'))
function App() {
return (
<Suspense fallback={<div className="loading">Loading...</div>}>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
)
}错误处理
import { lazy, Suspense } from 'react'
import { ErrorBoundary } from './ErrorBoundary'
// 结合错误边界
function App() {
return (
<ErrorBoundary fallback={<ErrorPage />}>
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/dashboard" element={
<LazyComponent importFn={() => import('./pages/Dashboard')} />
} />
</Routes>
</Suspense>
</ErrorBoundary>
)
}虚拟列表
react-window 渲染可视区域内的行,不渲染不可见行。
npm install react-window @types/react-windowimport { FixedSizeList as List } from 'react-window'
interface ItemData {
items: string[]
}
function Row({ index, style, data }: { index: number; style: React.CSSProperties; data: ItemData }) {
return (
<div style={style} className="item">
{data.items[index]}
</div>
)
}
function VirtualList() {
const items = Array.from({ length: 100000 }, (_, i) => `Item ${i}`)
return (
<List
height={600} // 容器高度
itemCount={items.length} // 总数
itemSize={50} // 每行高度
width="100%"
itemData={{ items }}
>
{Row}
</List>
)
}可变高度
import { VariableSizeList } from 'react-window'
// 每行高度不同
<VariableSizeList
height={600}
itemCount={items.length}
itemSize={index => items[index].height}
width="100%"
>
{Row}
</VariableSizeList>Bundle 分析
npm install -D vite-plugin-visualizer// vite.config.ts
import { visualizer } from 'vite-plugin-visualizer'
export default defineConfig({
plugins: [
react(),
visualizer({ open: true }),
],
})npm run build # 自动打开分析页面小结
React.lazy+Suspense按需加载组件,减少首屏 Bundle。- 可配合 ErrorBoundary 处理加载失败。
react-window虚拟列表处理万级数据。- vite-plugin-visualizer 分析 Bundle 大小,找优化点。
- 常见大模块:moment.js → date-fns、lodash → 按需导入。
