Deployment
Learn how to deploy your VitePress site to various hosting platforms and configure it for production.
Overview
VitePress generates static files that can be deployed to any static hosting service. The build process creates an optimized production bundle in the dist
directory.
Building for Production
Basic Build
bash
# Build the site
npm run build
# Preview the build locally
npm run preview
Build Configuration
js
// .vitepress/config.js
export default {
base: '/my-project/', // For GitHub Pages subdirectory
outDir: '../dist', // Custom output directory
build: {
minify: 'terser',
sourcemap: false,
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue']
}
}
}
}
}
GitHub Pages
Automatic Deployment with GitHub Actions
Create .github/workflows/deploy.yml
:
yaml
name: Deploy VitePress site to Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
cache: npm
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Install dependencies
run: npm ci
- name: Build with VitePress
run: npm run build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/.vitepress/dist
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: build
runs-on: ubuntu-latest
name: Deploy
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Manual Deployment
bash
# Build the site
npm run build
# Navigate to build output directory
cd docs/.vitepress/dist
# Initialize git repository
git init
git add -A
git commit -m 'deploy'
# Deploy to GitHub Pages
git push -f git@github.com:username/repo.git main:gh-pages
Configuration for GitHub Pages
js
// .vitepress/config.js
export default {
base: '/repository-name/', // Replace with your repo name
themeConfig: {
editLink: {
pattern: 'https://github.com/username/repo/edit/main/docs/:path'
}
}
}
Netlify
Automatic Deployment
- Connect Repository: Link your GitHub/GitLab repository to Netlify
- Build Settings:
- Build command:
npm run build
- Publish directory:
docs/.vitepress/dist
- Build command:
Netlify Configuration File
Create netlify.toml
:
toml
[build]
command = "npm run build"
publish = "docs/.vitepress/dist"
[build.environment]
NODE_VERSION = "18"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
[[headers]]
for = "/assets/*"
[headers.values]
Cache-Control = "max-age=31536000, immutable"
Environment Variables
toml
[build.environment]
NODE_ENV = "production"
VITE_API_URL = "https://api.example.com"
Vercel
Automatic Deployment
- Import Project: Connect your repository to Vercel
- Build Settings:
- Framework Preset: Other
- Build Command:
npm run build
- Output Directory:
docs/.vitepress/dist
Vercel Configuration
Create vercel.json
:
json
{
"buildCommand": "npm run build",
"outputDirectory": "docs/.vitepress/dist",
"framework": null,
"rewrites": [
{
"source": "/(.*)",
"destination": "/index.html"
}
]
}
Environment Variables
Set in Vercel dashboard or use .env.local
:
bash
VITE_API_URL=https://api.example.com
Cloudflare Pages
Automatic Deployment
- Connect Repository: Link your repository to Cloudflare Pages
- Build Settings:
- Build command:
npm run build
- Build output directory:
docs/.vitepress/dist
- Build command:
Custom Domain
js
// .vitepress/config.js
export default {
base: '/', // Use root for custom domain
head: [
['link', { rel: 'canonical', href: 'https://yourdomain.com' }]
]
}
AWS S3 + CloudFront
S3 Bucket Setup
bash
# Create S3 bucket
aws s3 mb s3://your-bucket-name
# Configure bucket for static website hosting
aws s3 website s3://your-bucket-name \
--index-document index.html \
--error-document 404.html
Deployment Script
bash
#!/bin/bash
# deploy.sh
# Build the site
npm run build
# Sync to S3
aws s3 sync docs/.vitepress/dist/ s3://your-bucket-name \
--delete \
--cache-control "max-age=31536000" \
--exclude "*.html" \
--exclude "*.xml"
# Upload HTML files with different cache settings
aws s3 sync docs/.vitepress/dist/ s3://your-bucket-name \
--delete \
--cache-control "max-age=0, no-cache, no-store, must-revalidate" \
--include "*.html" \
--include "*.xml"
# Invalidate CloudFront cache
aws cloudfront create-invalidation \
--distribution-id YOUR_DISTRIBUTION_ID \
--paths "/*"
CloudFront Configuration
json
{
"Origins": [{
"DomainName": "your-bucket-name.s3.amazonaws.com",
"Id": "S3-your-bucket-name",
"S3OriginConfig": {
"OriginAccessIdentity": ""
}
}],
"DefaultCacheBehavior": {
"TargetOriginId": "S3-your-bucket-name",
"ViewerProtocolPolicy": "redirect-to-https",
"CachePolicyId": "4135ea2d-6df8-44a3-9df3-4b5a84be39ad"
}
}
Docker Deployment
Dockerfile
dockerfile
# Build stage
FROM node:18-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM nginx:alpine as production-stage
COPY --from=build-stage /app/docs/.vitepress/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Nginx Configuration
nginx
# nginx.conf
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Handle client-side routing
location / {
try_files $uri $uri/ /index.html;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
}
}
Docker Compose
yaml
# docker-compose.yml
version: '3.8'
services:
vitepress:
build: .
ports:
- "80:80"
restart: unless-stopped
# Optional: Add SSL with Let's Encrypt
certbot:
image: certbot/certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
Custom Server Deployment
Express.js Server
js
// server.js
const express = require('express')
const path = require('path')
const app = express()
// Serve static files
app.use(express.static(path.join(__dirname, 'docs/.vitepress/dist')))
// Handle client-side routing
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'docs/.vitepress/dist/index.html'))
})
const port = process.env.PORT || 3000
app.listen(port, () => {
console.log(`Server running on port ${port}`)
})
PM2 Configuration
json
{
"name": "vitepress-site",
"script": "server.js",
"instances": "max",
"exec_mode": "cluster",
"env": {
"NODE_ENV": "production",
"PORT": 3000
}
}
Performance Optimization
Build Optimization
js
// .vitepress/config.js
export default {
build: {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
},
rollupOptions: {
output: {
manualChunks: {
vendor: ['vue'],
utils: ['lodash', 'date-fns']
}
}
}
}
}
Asset Optimization
js
export default {
vite: {
build: {
assetsInlineLimit: 4096,
cssCodeSplit: true,
sourcemap: false
}
}
}
CDN Configuration
js
export default {
head: [
['link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' }],
['link', { rel: 'dns-prefetch', href: 'https://cdn.jsdelivr.net' }]
],
vite: {
build: {
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue'
}
}
}
}
}
}
SSL/HTTPS Setup
Let's Encrypt with Certbot
bash
# Install Certbot
sudo apt install certbot python3-certbot-nginx
# Obtain SSL certificate
sudo certbot --nginx -d yourdomain.com
# Auto-renewal
sudo crontab -e
# Add: 0 12 * * * /usr/bin/certbot renew --quiet
Cloudflare SSL
js
// .vitepress/config.js
export default {
head: [
['meta', { 'http-equiv': 'Content-Security-Policy', content: 'upgrade-insecure-requests' }]
]
}
Monitoring and Analytics
Google Analytics
js
// .vitepress/config.js
export default {
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
js
// .vitepress/theme/index.js
export default {
enhanceApp({ app }) {
app.config.errorHandler = (err, vm, info) => {
// Send error to tracking service
console.error('Vue error:', err, info)
}
}
}
Troubleshooting
Common Issues
404 Errors on Refresh
- Configure server to serve
index.html
for all routes - Set up proper redirects in hosting platform
Asset Loading Issues
- Check
base
configuration in config file - Verify asset paths are correct
- Ensure proper CORS headers
Build Failures
- Check Node.js version compatibility
- Verify all dependencies are installed
- Review build logs for specific errors
Debug Mode
bash
# Enable debug mode
DEBUG=vitepress:* npm run build
# Verbose logging
npm run build -- --debug
Best Practices
Pre-deployment Checklist
- [ ] Test build locally with
npm run preview
- [ ] Verify all links work correctly
- [ ] Check responsive design on different devices
- [ ] Test loading performance
- [ ] Validate HTML and accessibility
- [ ] Set up proper redirects for old URLs
- [ ] Configure caching headers
- [ ] Set up monitoring and analytics
- [ ] Test SSL certificate
- [ ] Verify SEO meta tags
Security Considerations
- Use HTTPS everywhere
- Set proper security headers
- Keep dependencies updated
- Use environment variables for secrets
- Implement Content Security Policy
- Regular security audits