Skip to content

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 ​

  1. Connect Repository: Link your GitHub/GitLab repository to Netlify
  2. Build Settings:
    • Build command: npm run build
    • Publish directory: docs/.vitepress/dist

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 ​

  1. Import Project: Connect your repository to Vercel
  2. 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 ​

  1. Connect Repository: Link your repository to Cloudflare Pages
  2. Build Settings:
    • Build command: npm run build
    • Build output directory: docs/.vitepress/dist

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

Next Steps ​

VitePress Development Guide