Skip to content
VitePress 博客部署优化:Vercel 部署与性能调优

VitePress 博客部署优化:Vercel 部署与性能调优

VitePress

基于 GABA Blog 实际项目,详细讲解 VitePress 博客在 Vercel 上的部署优化策略,包括缓存配置、性能调优、监控分析和最佳实践

标签:
Vercel
发布于 2025年12月19日

部署架构概述

GABA Blog 选择 Vercel 作为部署平台,主要基于以下考虑:

  1. 开发者友好:无缝的 Git 集成和自动部署
  2. 性能优秀:全球 CDN 和边缘网络
  3. 成本效益:个人项目免费额度充足
  4. 功能丰富:支持 Serverless Functions、环境变量等
  5. 监控完善:内置性能监控和分析工具

Vercel 配置详解

vercel.json 配置解析

json
{
  "headers": [
    {
      "source": "/assets/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "max-age=31536000, immutable"
        }
      ]
    }
  ]
}

配置说明

  1. 缓存策略:静态资源(assets)设置一年缓存(31536000秒)
  2. immutable 标志:资源内容不会改变,浏览器可以永久缓存
  3. 路径匹配:使用正则表达式匹配 /assets/ 目录下的所有文件

缓存策略优化

静态资源缓存策略

1. 资源分类与缓存策略

资源类型缓存策略说明
HTML 文件max-age=3600, must-revalidate内容可能更新,需要重新验证
CSS/JS 文件max-age=31536000, immutable通过文件哈希确保内容不变
图片资源max-age=31536000, immutable内容不变,永久缓存
字体文件max-age=31536000, immutable内容不变,永久缓存

2. 完整的缓存配置示例

json
{
  "headers": [
    {
      "source": "/assets/(.*)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "max-age=31536000, immutable"
        },
        {
          "key": "Vary",
          "value": "Accept-Encoding"
        }
      ]
    },
    {
      "source": "/(.*).(html|htm)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "max-age=3600, must-revalidate"
        }
      ]
    },
    {
      "source": "/(.*).(css|js)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "max-age=31536000, immutable"
        }
      ]
    }
  ]
}

浏览器缓存优化

Service Worker 缓存策略

javascript
// public/sw.js
const CACHE_NAME = 'gaba-blog-v1';
const STATIC_ASSETS = [
  '/',
  '/index.html',
  '/assets/main.css',
  '/assets/main.js',
  '/fonts/inter-regular.woff2',
  '/favicon.ico'
];

// 安装时缓存核心资源
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(STATIC_ASSETS))
      .then(() => self.skipWaiting())
  );
});

// 激活时清理旧缓存
self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          if (cacheName !== CACHE_NAME) {
            return caches.delete(cacheName);
          }
        })
      );
    }).then(() => self.clients.claim())
  );
});

// 拦截请求并返回缓存
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        if (response) {
          return response;
        }
        
        // 对于 HTML 请求,使用网络优先策略
        if (event.request.headers.get('Accept').includes('text/html')) {
          return fetch(event.request)
            .then(response => {
              // 不缓存 HTML 响应,因为内容可能更新
              return response;
            })
            .catch(() => {
              // 网络失败时返回离线页面
              return caches.match('/offline.html');
            });
        }
        
        // 对于其他资源,使用缓存优先策略
        return fetch(event.request)
          .then(response => {
            // 检查响应是否有效
            if (!response || response.status !== 200 || response.type !== 'basic') {
              return response;
            }
            
            // 克隆响应以进行缓存
            const responseToCache = response.clone();
            
            caches.open(CACHE_NAME)
              .then(cache => {
                cache.put(event.request, responseToCache);
              });
            
            return response;
          })
          .catch(() => {
            // 对于图片等资源,可以返回占位符
            if (event.request.destination === 'image') {
              return caches.match('/assets/placeholder.jpg');
            }
          });
      })
  );
});

构建优化配置

Vite 构建配置优化

typescript
// .vitepress/config.mts 中的构建配置
vite: {
  build: {
    // 代码分割配置
    cssCodeSplit: true,
    sourcemap: false,
    minify: "esbuild",
    
    // Rollup 配置
    rollupOptions: {
      output: {
        // 手动代码分割
        manualChunks: {
          // 将 Vue 相关库单独打包
          vue: ['vue', 'vue-router'],
          // 将 UI 库单独打包
          ui: ['@iconify/vue', 'motion-v'],
          // 将工具库单独打包
          utils: ['lodash-es', 'dayjs'],
        },
        
        // 文件命名策略
        chunkFileNames: 'assets/js/[name]-[hash].js',
        entryFileNames: 'assets/js/[name]-[hash].js',
        assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
      },
    },
    
    // 构建目标
    target: 'es2020',
    
    // 资源大小限制
    assetsInlineLimit: 4096, // 4KB 以下资源内联
    
    // 块大小警告限制
    chunkSizeWarningLimit: 1000, // 1MB
  },
}

构建优化策略

  1. 代码分割:将第三方库分离,提高缓存利用率
  2. 文件哈希:使用内容哈希命名,支持长期缓存
  3. 资源内联:小资源内联减少 HTTP 请求
  4. 目标版本:使用现代 JavaScript 特性

性能监控与分析

Core Web Vitals 监控

1. Google Analytics 4 集成

html
<!-- 在 head 中添加 GA4 跟踪代码 -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXXXXX');
</script>

2. 自定义性能监控

typescript
// 性能监控工具
export class PerformanceMonitor {
  static trackPageView() {
    if (typeof window.gtag !== 'undefined') {
      window.gtag('event', 'page_view', {
        page_title: document.title,
        page_location: window.location.href,
        page_path: window.location.pathname
      });
    }
  }

  static trackCustomMetric(name: string, value: number) {
    if (typeof window.gtag !== 'undefined') {
      window.gtag('event', 'custom_metric', {
        metric_name: name,
        metric_value: value
      });
    }
  }

  static trackLCP(entry: PerformanceEntry) {
    this.trackCustomMetric('lcp', entry.startTime);
  }

  static trackFID(entry: PerformanceEntry) {
    this.trackCustomMetric('fid', entry.duration);
  }
}

// 监听 Core Web Vitals
if ('PerformanceObserver' in window) {
  const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      if (entry.entryType === 'largest-contentful-paint') {
        PerformanceMonitor.trackLCP(entry);
      } else if (entry.entryType === 'first-input') {
        PerformanceMonitor.trackFID(entry);
      }
    }
  });

  observer.observe({ entryTypes: ['largest-contentful-paint', 'first-input'] });
}

构建分析工具

使用 rollup-plugin-visualizer

javascript
// 安装依赖
// pnpm add -D rollup-plugin-visualizer

// 在 vite 配置中添加
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  vite: {
    plugins: [
      visualizer({
        filename: 'dist/stats.html',
        open: true,
        gzipSize: true,
        brotliSize: true
      })
    ]
  }
});

部署流程优化

CI/CD 自动化部署

1. GitHub Actions 工作流

yaml
# .github/workflows/deploy.yml
name: Deploy to Vercel

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

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'pnpm'
    
    - name: Install dependencies
      run: pnpm install --frozen-lockfile
    
    - name: Build
      run: pnpm build
    
    - name: Test build output
      run: |
        if [ -d "dist" ]; then
          echo "Build successful"
          ls -la dist/
        else
          echo "Build failed"
          exit 1
        fi

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'pnpm'
    
    - name: Install dependencies
      run: pnpm install --frozen-lockfile
    
    - name: Deploy to Vercel
      uses: amondnet/vercel-action@v20
      with:
        vercel-token: ${{ secrets.VERCEL_TOKEN }}
        vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
        vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
        vercel-args: '--prod'

2. 环境变量管理

bash
# .env.local
VITE_APP_TITLE=GABA Blog
VITE_APP_DESCRIPTION=分享日常随笔
VITE_GA_MEASUREMENT_ID=G-XXXXXXXXXX

# vercel.json 环境变量配置
{
  "env": {
    "VITE_APP_TITLE": "GABA Blog",
    "VITE_APP_DESCRIPTION": "分享日常随笔"
  }
}

安全优化策略

1. 安全头部配置

json
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        },
        {
          "key": "X-Frame-Options",
          "value": "DENY"
        },
        {
          "key": "X-XSS-Protection",
          "value": "1; mode=block"
        },
        {
          "key": "Referrer-Policy",
          "value": "strict-origin-when-cross-origin"
        }
      ]
    }
  ]
}

2. CSP 内容安全策略

html
<meta http-equiv="Content-Security-Policy" content="
  default-src 'self';
  script-src 'self' 'unsafe-inline' https://www.googletagmanager.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self' https://www.google-analytics.com;
">

故障排除与调试

1. 部署问题排查

bash
# 本地构建测试
pnpm build

# 预览构建结果
pnpm preview

# 检查构建输出
ls -la dist/

# 检查文件大小
find dist/ -type f -name "*.js" -exec du -h {} \;

# 检查缓存头
curl -I https://blog.crudclass.com/assets/main.js

2. 性能问题排查

javascript
// 性能调试工具
const measurePerformance = (name: string, callback: () => void) => {
  const start = performance.now();
  callback();
  const duration = performance.now() - start;
  
  console.log(`[Performance] ${name}: ${duration.toFixed(2)}ms`);
  
  if (duration > 100) {
    console.warn(`[Performance Warning] ${name} took ${duration.toFixed(2)}ms`);
  }
};

// 使用示例
measurePerformance('Article Load', () => {
  loadArticleContent();
});

最佳实践总结

1. 部署最佳实践

  • ✅ 使用 immutable 缓存策略优化静态资源
  • ✅ 配置合理的 CDN 缓存规则
  • ✅ 实现 Service Worker 离线支持
  • ✅ 设置安全头部保护网站安全
  • ✅ 监控 Core Web Vitals 指标

2. 性能最佳实践

  • ✅ 代码分割和懒加载
  • ✅ 资源压缩和优化
  • ✅ 图片懒加载和响应式图片
  • ✅ 字体优化和预加载
  • ✅ 减少第三方依赖

3. 监控最佳实践

  • ✅ 集成 Google Analytics 4
  • ✅ 监控 Core Web Vitals
  • ✅ 使用构建分析工具
  • ✅ 设置错误监控
  • ✅ 定期性能审计

总结

通过合理的部署优化策略,GABA Blog 在 Vercel 上实现了优秀的性能表现:

  1. 极快的加载速度:通过缓存策略和 CDN 优化
  2. 优秀的用户体验:通过性能监控和优化
  3. 可靠的部署流程:通过 CI/CD 自动化
  4. 完善的安全防护:通过安全头部配置
  5. 持续的监控改进:通过数据分析优化

这些优化策略不仅提升了博客的性能和用户体验,也为后续的扩展和维护打下了坚实的基础。部署优化是一个持续的过程,需要根据实际监控数据和用户反馈不断调整和改进。

通过本文的指导,您可以构建出高性能、高可用的 VitePress 博客部署方案,为用户提供优秀的访问体验。

Last updated: