单页应用(SPA)在用户体验上具有天然优势,但随着项目规模的扩大,首屏加载性能可能成为瓶颈。本文将从代码分割、资源优化、服务端渲染(SSR)等维度,手把手教你构建全链路优化方案,并附带代码实战!
一、代码分割:按需加载关键资源
问题:传统SPA打包后生成单一bundle.js,首屏需加载冗余代码。
方案:通过动态导入(Dynamic Import)分割代码,结合路由懒加载。
1.1 路由级代码分割(React + React Router)
// 使用React.lazy + Suspense实现懒加载
import { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
const Home = lazy(() => import('./Home'));
const Dashboard = lazy(() => import('./Dashboard'));
function App() {
return (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Suspense>
</Router>
);
}
1.2 组件级代码分割(Webpack Magic Comments)
通过/* webpackPrefetch: true */预取非关键资源:
const Modal = lazy(() => import(
/* webpackChunkName: "modal" */
/* webpackPrefetch: true */
'./Modal'
));
二、资源压缩与缓存策略
2.1 Gzip/Brotli压缩
Nginx配置示例:
gzip on;
gzip_types text/plain text/css application/json application/javascript;
brotli on; # 需安装Brotli模块
brotli_types text/plain text/css application/json application/javascript;
2.2 长效缓存(Long-term Caching)
利用Webpack的contenthash生成唯一文件名:
// webpack.config.js
output: {
filename: '[name].[contenthash].js',
chunkFilename: '[name].[contenthash].chunk.js',
}
Nginx缓存策略:
location /static {
expires 1y;
add_header Cache-Control "public, immutable";
}
三、服务端渲染(SSR)提速首屏
SSR核心价值:服务端生成完整HTML,减少客户端渲染阻塞时间。
3.1 SSR基础实现(以Next.js为例)
// pages/index.js
export default function Home({ serverTime }) {
return <div>Server Time: {serverTime}</div>;
}
// 服务端获取数据
export async function getServerSideProps() {
return {
props: {
serverTime: new Date().toISOString(),
},
};
}
3.2 流式渲染(React 18+)
通过renderToPipeableStream分块传输内容:
import { renderToPipeableStream } from 'react-dom/server';
app.use('*', (req, res) => {
const stream = renderToPipeableStream(<App />, {
onShellReady() {
res.setHeader('Content-type', 'text/html');
stream.pipe(res);
},
bootstrapScripts: ['/main.js'],
});
});
四、性能监控与持续优化
- Lighthouse分析:定期检测首屏指标(FCP, LCP)。
- 资源加载瀑布图:通过Chrome DevTools定位阻塞请求。
- 真实用户监控(RUM) :接入Sentry、New Relic等工具。
五、总结与效果对比
| 优化阶段 | 首屏FCP(Before) | 首屏FCP(After) |
|---|---|---|
| 未优化 | 3.8s | - |
| 代码分割 | - | 2.1s |
| SSR + 流式渲染 | - | 0.9s |
优化要点总结:
- 代码分割减少首屏资源体积。
- 资源压缩与缓存提升加载效率。
- SSR+流式渲染消灭空白等待时间。
相关技术栈:Webpack、React、Next.js、Nginx、React Router