Deployment

Frontend Deployment Guide

Build Process

Production Build

# Install dependencies
npm install

# Build for production
npm run build

# Output directory: dist/

Environment Configuration

Environment Variables

# .env.production
VITE_API_URL=https://api.haddock.example.com
VITE_WS_URL=wss://api.haddock.example.com/events
VITE_GITHUB_CLIENT_ID=your_github_client_id

Configuration File

// public/config.json
{
  "apiUrl": "https://api.haddock.example.com",
  "wsUrl": "wss://api.haddock.example.com/events",
  "githubClientId": "your_github_client_id"
}

Docker Deployment

Dockerfile

# Stage 1: Build
FROM node:18-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Stage 2: Serve
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

Docker Compose

version: '3.8'
services:
  frontend:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "80:80"
    environment:
      - NODE_ENV=production

Nginx Configuration

Basic Configuration

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

    # Enable gzip compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml;

    # SPA routing
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache static assets
    location /assets/ {
        expires 1y;
        add_header Cache-Control "public, no-transform";
    }
}

CI/CD Pipeline

GitHub Actions Workflow

name: Deploy Frontend

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./dist

Performance Optimization

Build Optimization

  • Route-based code splitting
  • Asset compression
  • Tree shaking
  • Image optimization

Caching Strategy

// vite.config.ts
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ['react', 'react-dom'],
          // Add more chunks as needed
        }
      }
    }
  }
})

Monitoring

Error Tracking

// src/main.tsx
if (import.meta.env.PROD) {
  setupErrorTracking({
    dsn: import.meta.env.VITE_SENTRY_DSN,
    environment: 'production'
  })
}

Performance Monitoring

// src/app.tsx
import { web-vitals } from 'web-vitals'

web-vitals.report(console.log)

Security Considerations

Headers Configuration

# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "default-src 'self';" always;

Runtime Security

// CSP nonce generation for inline scripts
const nonce = crypto.randomBytes(16).toString('base64')
document.querySelector('script')?.setAttribute('nonce', nonce)