Skip to content

部署

构建 Rspress 文档网站后,下一步是部署它以使用户能够访问。本章介绍流行平台的部署策略和最佳实践。

部署概述

部署什么?

运行 npm run build 后,您将拥有准备部署的静态文件:

doc_build/
├── index.html
├── guide/
│   └── *.html
├── api/
│   └── *.html
├── assets/
│   ├── chunks/
│   ├── css/
│   └── images/
└── _rspress/

这些是纯静态文件,可以托管在任何地方。

部署选项

  • 静态托管: Vercel, Netlify, GitHub Pages, Cloudflare Pages
  • 传统托管: Apache, Nginx, AWS S3
  • CDN: CloudFront, Fastly, Akamai
  • 容器: Docker, Kubernetes

Vercel 部署

快速部署

使用一个命令部署到 Vercel:

bash
# 安装 Vercel CLI
npm install -g vercel

# 部署
vercel

# 按照提示配置和部署

GitHub 集成

  1. 推送到 GitHub:
bash
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/username/repo.git
git push -u origin main
  1. 连接到 Vercel:
  • 访问 vercel.com
  • 点击"Import Project"
  • 选择您的仓库
  • 配置构建设置:
    • 构建命令: npm run build
    • 输出目录: doc_build
    • 安装命令: npm install
  1. 部署:
  • Vercel 在推送时自动部署
  • Pull Request 的预览部署
  • 从主分支进行生产部署

Vercel 配置

创建 vercel.json:

json
{
  "buildCommand": "npm run build",
  "outputDirectory": "doc_build",
  "devCommand": "npm run dev",
  "installCommand": "npm install",
  "framework": null,
  "cleanUrls": true,
  "trailingSlash": false,
  "headers": [
    {
      "source": "/assets/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    }
  ]
}

Netlify 部署

拖放

快速部署的最简单方法:

  1. 构建您的网站: npm run build
  2. 访问 netlify.com
  3. doc_build 文件夹拖到部署区域
  4. 网站上线!

Git 集成

  1. 推送到 Git 仓库(GitHub, GitLab, Bitbucket)

  2. 连接到 Netlify:

  • 登录 Netlify
  • 点击"New site from Git"
  • 选择您的仓库
  • 配置:
    • 构建命令: npm run build
    • 发布目录: doc_build
  1. 部署:
  • 推送时自动部署
  • PR 的部署预览
  • 回滚能力

Netlify 配置

创建 netlify.toml:

toml
[build]
  command = "npm run build"
  publish = "doc_build"

[build.environment]
  NODE_VERSION = "18"

[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

[[headers]]
  for = "/assets/*"
  [headers.values]
    Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
  for = "/*.html"
  [headers.values]
    Cache-Control = "public, max-age=0, must-revalidate"

GitHub Pages

GitHub Actions 部署

创建 .github/workflows/deploy.yml:

yaml
name: 部署到 GitHub Pages

on:
  push:
    branches: [main]

# 设置 GITHUB_TOKEN 的权限
permissions:
  contents: read
  pages: write
  id-token: write

# 允许一个并发部署
concurrency:
  group: "pages"
  cancel-in-progress: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build
        env:
          NODE_ENV: production

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v2
        with:
          path: ./doc_build

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2

GitHub Pages 配置

如果部署到仓库路径,配置 base path:

typescript
// rspress.config.ts
export default defineConfig({
  base: '/repository-name/',  // 用于 username.github.io/repository-name
  // base: '/',               // 用于 username.github.io
});

启用 GitHub Pages

  1. 转到仓库设置
  2. 导航到 Pages 部分
  3. 选择"GitHub Actions"作为源
  4. 推送到主分支以触发部署

Cloudflare Pages

Wrangler CLI

bash
# 安装 Wrangler
npm install -g wrangler

# 登录 Cloudflare
wrangler login

# 部署
wrangler pages publish doc_build

Git 集成

  1. 连接仓库:
  • 登录 Cloudflare 仪表板
  • 转到 Pages
  • 点击"Create a project"
  • 连接 GitHub/GitLab 仓库
  1. 构建设置:
构建命令: npm run build
构建输出目录: doc_build
根目录: /
  1. 环境变量(如果需要):
NODE_VERSION=18

AWS S3 + CloudFront

S3 存储桶设置

bash
# 安装 AWS CLI
npm install -g aws-cli

# 配置 AWS 凭证
aws configure

# 创建 S3 存储桶
aws s3 mb s3://my-docs-site

# 启用静态网站托管
aws s3 website s3://my-docs-site/ \
  --index-document index.html \
  --error-document 404.html

# 上传文件
npm run build
aws s3 sync doc_build/ s3://my-docs-site/ \
  --delete \
  --cache-control "public, max-age=31536000" \
  --exclude "*.html" \
  --exclude "sitemap.xml"

# 使用不同缓存上传 HTML
aws s3 sync doc_build/ s3://my-docs-site/ \
  --delete \
  --cache-control "public, max-age=0, must-revalidate" \
  --exclude "*" \
  --include "*.html" \
  --include "sitemap.xml"

Docker 部署

Dockerfile

dockerfile
# 构建阶段
FROM node:18-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

# 生产阶段
FROM nginx:alpine

COPY --from=builder /app/doc_build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

Nginx 配置

nginx
# nginx.conf
server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;

    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    # 缓存静态资源
    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # 处理客户端路由
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 安全头
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
}

构建和运行

bash
# 构建镜像
docker build -t my-docs .

# 运行容器
docker run -d -p 8080:80 my-docs

# 访问 http://localhost:8080

自定义服务器部署

Node.js 服务器

javascript
// server.js
const express = require('express');
const path = require('path');

const app = express();
const PORT = process.env.PORT || 3000;

// 提供静态文件
app.use(express.static(path.join(__dirname, 'doc_build'), {
  maxAge: '1y',
  etag: true,
}));

// 处理客户端路由
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'doc_build', 'index.html'));
});

app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
});

Apache 配置

apache
# .htaccess
<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /

  # 处理客户端路由
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

# 缓存控制
<IfModule mod_headers.c>
  <FilesMatch "\.(html|xml)$">
    Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
  </FilesMatch>

  <FilesMatch "\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2)$">
    Header set Cache-Control "max-age=31536000, public, immutable"
  </FilesMatch>
</IfModule>

部署优化

构建优化

typescript
// rspress.config.ts
export default defineConfig({
  builderConfig: {
    output: {
      minify: true,
      cleanDistPath: true,
    },
    performance: {
      chunkSplit: {
        strategy: 'split-by-experience',
      },
      preload: true,
      prefetch: true,
    },
  },
});

压缩

启用 Gzip/Brotli 压缩:

bash
# 预压缩文件
npm install -g gzipper

# Gzip 压缩
gzipper compress ./doc_build

# Brotli 压缩
gzipper compress ./doc_build --brotli

环境特定构建

多环境

json
// package.json
{
  "scripts": {
    "build": "rspress build",
    "build:staging": "NODE_ENV=staging rspress build",
    "build:production": "NODE_ENV=production rspress build"
  }
}

环境配置

typescript
// rspress.config.ts
const isProd = process.env.NODE_ENV === 'production';

export default defineConfig({
  base: isProd ? '/' : '/staging/',
  head: [
    ['meta', { name: 'robots', content: isProd ? 'index,follow' : 'noindex,nofollow' }],
  ],
});

监控和分析

Google Analytics

typescript
export default defineConfig({
  head: [
    [
      'script',
      {
        async: true,
        src: 'https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID',
      },
    ],
    [
      'script',
      {},
      `
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());
        gtag('config', 'GA_MEASUREMENT_ID');
      `,
    ],
  ],
});

部署检查清单

部署前:

  • [ ] 成功运行 npm run build
  • [ ] 使用 npm run preview 测试
  • [ ] 验证所有页面正确加载
  • [ ] 在移动设备上检查响应式设计
  • [ ] 测试所有内部链接
  • [ ] 验证 HTML
  • [ ] 检查 Lighthouse 分数
  • [ ] 配置适当的缓存头
  • [ ] 设置 HTTPS/SSL
  • [ ] 配置自定义域名
  • [ ] 设置监控/分析
  • [ ] 创建备份策略
  • [ ] 记录部署过程

故障排除

404 错误

  1. 客户端路由: 为 SPA 配置服务器
  2. Base path: 检查 base 配置是否与部署路径匹配
  3. 大小写敏感: URL 在 Linux 服务器上区分大小写

构建失败

bash
# 清除缓存并重建
rm -rf node_modules/.rspress doc_build
npm install
npm run build

加载缓慢

  1. 启用压缩(Gzip/Brotli)
  2. 为资源使用 CDN
  3. 优化图片
  4. 检查 bundle 大小
  5. 启用 HTTP/2

最佳实践

性能

  • 启用 CDN
  • 使用 HTTP/2
  • 启用压缩
  • 优化图片
  • 设置适当的缓存头
  • 最小化 JavaScript
  • 使用懒加载

安全性

  • 启用 HTTPS
  • 设置安全头
  • 验证用户输入
  • 保持依赖更新
  • 使用内容安全策略

可靠性

  • 自动化部署
  • 准备环境
  • 回滚能力
  • 健康检查
  • 错误监控
  • 备份策略

下一步

恭喜您完成 Rspress 教程!您现在具备以下知识:

  • 创建和构建文档网站
  • 配置导航和路由
  • 使用 MDX 和 React 组件
  • 处理静态资源
  • 实施国际化
  • 部署到各种平台

其他资源


快速部署

最快部署方式:

  1. Vercel: vercel (GitHub 集成)
  2. Netlify: 拖放 doc_build 文件夹
  3. GitHub Pages: 在仓库设置中启用

生产检查清单

  • ✅ 启用 HTTPS
  • ✅ 配置自定义域名
  • ✅ 设置分析
  • ✅ 错误监控激活
  • ✅ 配置备份
  • ✅ CI/CD 管道工作