Deployment
After building your Rspress documentation site, the next step is deploying it to make it accessible to users. This chapter covers deployment strategies for popular platforms and best practices.
Deployment Overview
What Gets Deployed?
After running npm run build, you'll have static files ready for deployment:
doc_build/
├── index.html
├── guide/
│ └── *.html
├── api/
│ └── *.html
├── assets/
│ ├── chunks/
│ ├── css/
│ └── images/
└── _rspress/These are pure static files that can be hosted anywhere.
Deployment Options
- Static Hosting: Vercel, Netlify, GitHub Pages, Cloudflare Pages
- Traditional Hosting: Apache, Nginx, AWS S3
- CDN: CloudFront, Fastly, Akamai
- Container: Docker, Kubernetes
Vercel Deployment
Quick Deploy
Deploy to Vercel with one command:
# Install Vercel CLI
npm install -g vercel
# Deploy
vercel
# Follow prompts to configure and deployGitHub Integration
- Push to GitHub:
git init
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/username/repo.git
git push -u origin main- Connect to Vercel:
- Visit vercel.com
- Click "Import Project"
- Select your repository
- Configure build settings:
- Build Command:
npm run build - Output Directory:
doc_build - Install Command:
npm install
- Build Command:
- Deploy:
- Vercel automatically deploys on push
- Preview deployments for pull requests
- Production deployment from main branch
Vercel Configuration
Create vercel.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"
}
]
}
],
"rewrites": [
{
"source": "/(.*)",
"destination": "/index.html"
}
]
}Netlify Deployment
Drag and Drop
Simplest method for quick deployment:
- Build your site:
npm run build - Go to netlify.com
- Drag
doc_buildfolder to deploy zone - Site is live!
Git Integration
Push to Git Repository (GitHub, GitLab, Bitbucket)
Connect to Netlify:
- Sign in to Netlify
- Click "New site from Git"
- Choose your repository
- Configure:
- Build command:
npm run build - Publish directory:
doc_build
- Build command:
- Deploy:
- Automatic deploys on push
- Deploy previews for PRs
- Rollback capability
Netlify Configuration
Create netlify.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"Netlify Functions
Add serverless functions if needed:
// netlify/functions/api.js
exports.handler = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({ message: 'Hello from Netlify!' }),
};
};GitHub Pages
GitHub Actions Deployment
Create .github/workflows/deploy.yml:
name: Deploy to GitHub Pages
on:
push:
branches: [main]
# Sets permissions of the GITHUB_TOKEN
permissions:
contents: read
pages: write
id-token: write
# Allow one concurrent deployment
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@v2Configuration for GitHub Pages
Configure base path if deploying to repository path:
// rspress.config.ts
export default defineConfig({
base: '/repository-name/', // For username.github.io/repository-name
// base: '/', // For username.github.io
});Enable GitHub Pages
- Go to repository Settings
- Navigate to Pages section
- Select "GitHub Actions" as source
- Push to main branch to trigger deployment
Cloudflare Pages
Wrangler CLI
# Install Wrangler
npm install -g wrangler
# Login to Cloudflare
wrangler login
# Deploy
wrangler pages publish doc_buildGit Integration
- Connect Repository:
- Sign in to Cloudflare Dashboard
- Go to Pages
- Click "Create a project"
- Connect GitHub/GitLab repository
- Build Settings:
Build command: npm run build
Build output directory: doc_build
Root directory: /- Environment Variables (if needed):
NODE_VERSION=18Cloudflare Configuration
Create wrangler.toml:
name = "my-rspress-site"
type = "webpack"
account_id = "your-account-id"
[site]
bucket = "./doc_build"
[build]
command = "npm run build"AWS S3 + CloudFront
S3 Bucket Setup
# Install AWS CLI
npm install -g aws-cli
# Configure AWS credentials
aws configure
# Create S3 bucket
aws s3 mb s3://my-docs-site
# Enable static website hosting
aws s3 website s3://my-docs-site/ \
--index-document index.html \
--error-document 404.html
# Upload files
npm run build
aws s3 sync doc_build/ s3://my-docs-site/ \
--delete \
--cache-control "public, max-age=31536000" \
--exclude "*.html" \
--exclude "sitemap.xml"
# Upload HTML with different cache
aws s3 sync doc_build/ s3://my-docs-site/ \
--delete \
--cache-control "public, max-age=0, must-revalidate" \
--exclude "*" \
--include "*.html" \
--include "sitemap.xml"CloudFront Distribution
- Create CloudFront distribution
- Origin: S3 bucket website endpoint
- Configure caching:
- Default TTL: 86400 (1 day)
- HTML files: 0 (always revalidate)
- Assets: 31536000 (1 year)
Automated Deployment
Create deployment script:
#!/bin/bash
# deploy.sh
echo "Building site..."
npm run build
echo "Uploading to S3..."
aws s3 sync doc_build/ s3://my-docs-site/ --delete
echo "Invalidating CloudFront cache..."
aws cloudfront create-invalidation \
--distribution-id YOUR_DISTRIBUTION_ID \
--paths "/*"
echo "Deployment complete!"Docker Deployment
Dockerfile
# Build stage
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
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 Configuration
# nginx.conf
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# Cache static assets
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Handle client-side routing
location / {
try_files $uri $uri/ /index.html;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
}Build and Run
# Build image
docker build -t my-docs .
# Run container
docker run -d -p 8080:80 my-docs
# Visit http://localhost:8080Custom Server Deployment
Node.js Server
// server.js
const express = require('express');
const path = require('path');
const app = express();
const PORT = process.env.PORT || 3000;
// Serve static files
app.use(express.static(path.join(__dirname, 'doc_build'), {
maxAge: '1y',
etag: true,
}));
// Handle client-side routing
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'doc_build', 'index.html'));
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});Apache Configuration
# .htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Handle client-side routing
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
# Cache control
<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>Deployment Optimization
Build Optimization
// rspress.config.ts
export default defineConfig({
builderConfig: {
output: {
minify: true,
cleanDistPath: true,
},
performance: {
chunkSplit: {
strategy: 'split-by-experience',
},
preload: true,
prefetch: true,
},
},
});Compression
Enable Gzip/Brotli compression:
# Pre-compress files
npm install -g gzipper
# Gzip compression
gzipper compress ./doc_build
# Brotli compression
gzipper compress ./doc_build --brotliCDN Integration
Use CDN for assets:
export default defineConfig({
builderConfig: {
output: {
assetPrefix: 'https://cdn.example.com/',
},
},
});Environment-specific Builds
Multiple Environments
// package.json
{
"scripts": {
"build": "rspress build",
"build:staging": "NODE_ENV=staging rspress build",
"build:production": "NODE_ENV=production rspress build"
}
}Environment Configuration
// 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' }],
],
});Monitoring and Analytics
Google Analytics
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');
`,
],
],
});Error Tracking
// Add error tracking (e.g., Sentry)
export default defineConfig({
head: [
[
'script',
{
src: 'https://browser.sentry-cdn.com/7.x.x/bundle.min.js',
crossorigin: 'anonymous',
},
],
[
'script',
{},
`
Sentry.init({
dsn: 'YOUR_SENTRY_DSN',
environment: 'production',
});
`,
],
],
});Deployment Checklist
Before deploying:
- [ ] Run
npm run buildsuccessfully - [ ] Test with
npm run preview - [ ] Verify all pages load correctly
- [ ] Check responsive design on mobile
- [ ] Test all internal links
- [ ] Validate HTML
- [ ] Check Lighthouse scores
- [ ] Configure proper caching headers
- [ ] Set up HTTPS/SSL
- [ ] Configure custom domain
- [ ] Set up monitoring/analytics
- [ ] Create backup strategy
- [ ] Document deployment process
Troubleshooting
404 Errors
- Client-side routing: Configure server for SPA
- Base path: Check
baseconfig matches deployment path - Case sensitivity: URLs are case-sensitive on Linux servers
Build Failures
# Clear cache and rebuild
rm -rf node_modules/.rspress doc_build
npm install
npm run buildSlow Loading
- Enable compression (Gzip/Brotli)
- Use CDN for assets
- Optimize images
- Check bundle sizes
- Enable HTTP/2
Cache Issues
# Bust cache by adding version query
# Or configure cache control headers properlyBest Practices
Performance
- Enable CDN
- Use HTTP/2
- Enable compression
- Optimize images
- Set proper cache headers
- Minimize JavaScript
- Use lazy loading
Security
- Enable HTTPS
- Set security headers
- Validate user input
- Keep dependencies updated
- Use Content Security Policy
Reliability
- Automated deployments
- Staging environment
- Rollback capability
- Health checks
- Error monitoring
- Backup strategy
Next Steps
Congratulations on completing the Rspress tutorial! You now have the knowledge to:
- Create and structure documentation sites
- Configure navigation and routing
- Use MDX and React components
- Handle static assets
- Implement internationalization
- Deploy to various platforms
Additional Resources
Quick Deploy
For fastest deployment:
- Vercel:
vercel(GitHub integration) - Netlify: Drag & drop
doc_buildfolder - GitHub Pages: Enable in repository settings
Production Checklist
- ✅ HTTPS enabled
- ✅ Custom domain configured
- ✅ Analytics set up
- ✅ Error monitoring active
- ✅ Backups configured
- ✅ CI/CD pipeline working