静态网站生成与服务端渲染
理解 Rspress 如何构建和渲染您的文档对于优化和部署至关重要。本章探讨静态网站生成(SSG)、服务端渲染(SSR)以及 Rspress 中的构建过程。
理解 SSG vs SSR
静态网站生成 (SSG)
SSG 在构建时预渲染所有页面,生成静态 HTML 文件:
构建时:
Markdown/MDX → HTML + CSS + JS → 静态文件
运行时:
用户请求 → 服务器 → 静态 HTML (快速!)优势:
- 极快的页面加载
- 更好的 SEO(内容立即可用)
- 更低的服务器成本(只需提供静态文件)
- 可以在简单托管上工作(不需要服务器)
- 可以在 CDN 上缓存
最适合:
- 文档网站
- 博客
- 营销页面
- 不经常变化的内容
服务端渲染 (SSR)
SSR 在每次请求时渲染页面:
运行时:
用户请求 → 服务器渲染 HTML → 响应
每个请求生成新的 HTML优势:
- 始终最新的内容
- 可以为用户个性化
- 访问请求数据
- 动态内容生成
最适合:
- 用户仪表板
- 个性化内容
- 频繁变化的数据
- 动态应用程序
Rspress 的方法
Rspress 主要使用 SSG,并具有可选的 SSR 能力:
typescript
// 默认: 纯 SSG
npm run build // 生成静态 HTML 文件
// 使用 SSR: 混合方法(高级)
// Rspress 也可以进行客户端水合构建过程
构建管道
理解 Rspress 的构建管道:
mermaid
graph LR
A[源文件] --> B[解析 MDX/MD]
B --> C[处理组件]
C --> D[生成路由]
D --> E[打包资源]
E --> F[生成 HTML]
F --> G[优化输出]
G --> H[静态文件]构建命令
bash
# 开发构建(快速,无优化)
npm run dev
# 生产构建(优化)
npm run build
# 预览生产构建
npm run preview构建输出
构建后,Rspress 生成:
doc_build/
├── index.html # 首页
├── guide/
│ ├── index.html # /guide/
│ ├── installation.html # /guide/installation
│ └── configuration.html # /guide/configuration
├── assets/
│ ├── chunks/ # 代码分割的 JS 块
│ ├── css/ # 编译的 CSS
│ └── images/ # 优化的图片
└── _rspress/
└── metadata.json # 构建元数据构建配置
基本构建设置
配置构建过程:
typescript
// rspress.config.ts
import { defineConfig } from 'rspress/config';
export default defineConfig({
root: 'docs',
outDir: 'doc_build', // 输出目录
// 构建配置
builderConfig: {
// 输出格式
output: {
cleanDistPath: true, // 构建前清理输出
distPath: {
root: 'doc_build',
},
},
// 性能
performance: {
chunkSplit: {
strategy: 'split-by-experience',
},
},
},
});优化设置
优化构建输出:
typescript
export default defineConfig({
builderConfig: {
// 压缩
output: {
minify: {
js: true,
css: true,
html: true,
},
},
// 代码分割
performance: {
chunkSplit: {
strategy: 'split-by-experience',
forceSplitting: [
/node_modules/,
],
},
},
// Source maps (用于调试)
output: {
sourceMap: {
js: 'source-map', // 或在生产中为 false
css: true,
},
},
},
});预渲染
预渲染如何工作
Rspress 使用 React SSR 预渲染页面:
- 解析内容: 读取和解析 Markdown/MDX
- 执行 React: 运行 React 组件生成 HTML
- 序列化状态: 捕获应用程序状态
- 生成 HTML: 创建带内联状态的完整 HTML
- 优化: 压缩和优化输出
预渲染配置
控制预渲染行为:
typescript
export default defineConfig({
// 预渲染所有路由
ssg: {
strict: true, // 在错误时构建失败
},
// 路由特定配置
route: {
// 要预渲染的路由
include: ['/', '/guide/**', '/api/**'],
// 要跳过的路由
exclude: ['**/draft/**'],
},
});水合
什么是水合?
水合使静态 HTML 具有交互性:
1. 服务器发送静态 HTML (快速初始加载)
2. 浏览器下载 JavaScript
3. React "水合" HTML (附加事件监听器)
4. 页面变得完全交互Rspress 中的水合
tsx
// 在构建期间 (SSG)
<button>点击我</button>
// 水合后 (交互式)
<button onClick={handleClick}>点击我</button>优化水合
typescript
// 懒加载重型组件
import { lazy, Suspense } from 'react';
const HeavyComponent = lazy(() => import('./HeavyComponent'));
export function Page() {
return (
<Suspense fallback={<div>加载中...</div>}>
<HeavyComponent />
</Suspense>
);
}代码分割
自动代码分割
Rspress 按路由自动分割代码:
首页: homepage.js (50KB)
指南页面: guide.js (30KB)
API 页面: api.js (40KB)
共享: vendor.js (100KB)手动代码分割
分割大型组件:
tsx
// 而不是这样(立即加载所有内容)
import { Chart } from './Chart';
import { Table } from './Table';
import { Graph } from './Graph';
// 这样做(按需加载)
const Chart = lazy(() => import('./Chart'));
const Table = lazy(() => import('./Table'));
const Graph = lazy(() => import('./Graph'));构建性能
测量构建时间
bash
# 测量构建时间
time npm run build
# 启用详细日志
npm run build -- --verbose
# 分析 bundle 大小
npm run build -- --analyze优化策略
- 减少依赖
typescript
// 重型库 (100KB)
import _ from 'lodash';
// 轻量替代 (10KB)
import debounce from 'lodash/debounce';- 懒加载重型内容
mdx
import { lazy } from 'react';
const VideoPlayer = lazy(() => import('./VideoPlayer'));
<Suspense fallback="加载中...">
<VideoPlayer />
</Suspense>- 优化图片
bash
# 在添加到文档之前
imagemin docs/images/* --out-dir=docs/images/optimized缓存
启用构建缓存以加快重建:
typescript
export default defineConfig({
builderConfig: {
// 启用缓存
cache: true,
},
});构建模式
开发模式
快速构建和热重载:
bash
npm run dev
# 特性:
- 快速增量构建
- 热模块替换
- 启用 source maps
- 无压缩
- 详细错误消息生产模式
优化的部署构建:
bash
npm run build
# 特性:
- 完全优化
- 启用压缩
- Tree shaking
- 死代码消除
- 资源优化预览模式
本地测试生产构建:
bash
# 先构建
npm run build
# 然后预览
npm run preview
# 在 http://localhost:4173 访问高级构建功能
自定义构建脚本
添加自定义构建脚本:
json
// package.json
{
"scripts": {
"build": "rspress build",
"build:analyze": "rspress build --analyze",
"build:staging": "NODE_ENV=staging rspress build",
"build:production": "NODE_ENV=production rspress build"
}
}环境变量
在构建中使用环境变量:
typescript
// rspress.config.ts
export default defineConfig({
define: {
'process.env.API_URL': JSON.stringify(
process.env.NODE_ENV === 'production'
? 'https://api.production.com'
: 'https://api.staging.com'
),
},
});SEO 优化
Meta 标签
在构建期间添加 meta 标签:
typescript
export default defineConfig({
head: [
['meta', { name: 'description', content: '网站描述' }],
['meta', { name: 'keywords', content: '关键词, 这里' }],
['meta', { property: 'og:title', content: '网站标题' }],
['meta', { property: 'og:description', content: '描述' }],
],
});故障排除
构建失败
- 内存问题
bash
# 增加 Node 内存
NODE_OPTIONS=--max_old_space_size=4096 npm run build- 缺少依赖
bash
# 清洁安装
rm -rf node_modules package-lock.json
npm install慢速构建
- 在生产中禁用 source maps
- 减少依赖
- 使用构建缓存
- 在构建前优化图片
- 将大页面分割成较小的页面
最佳实践
构建检查清单
在部署前:
- [ ] 运行生产构建
- [ ] 使用预览测试
- [ ] 检查 bundle 大小
- [ ] 验证所有页面加载
- [ ] 在移动设备上测试
- [ ] 检查 Lighthouse 分数
- [ ] 验证 HTML
- [ ] 测试所有链接
下一步
性能提示
- 启用构建缓存以加快重建
- 对大型站点使用代码分割
- 在添加图片之前优化它们
- 定期监控 bundle 大小
生产构建
- 在部署前始终测试生产构建
- 在生产中启用压缩
- 在生产中禁用 source maps
- 使用环境变量进行配置