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