部署架构概述
GABA Blog 选择 Vercel 作为部署平台,主要基于以下考虑:
- 开发者友好:无缝的 Git 集成和自动部署
- 性能优秀:全球 CDN 和边缘网络
- 成本效益:个人项目免费额度充足
- 功能丰富:支持 Serverless Functions、环境变量等
- 监控完善:内置性能监控和分析工具
Vercel 配置详解
vercel.json 配置解析
json
{
"headers": [
{
"source": "/assets/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=31536000, immutable"
}
]
}
]
}配置说明
- 缓存策略:静态资源(assets)设置一年缓存(31536000秒)
- immutable 标志:资源内容不会改变,浏览器可以永久缓存
- 路径匹配:使用正则表达式匹配
/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
},
}构建优化策略
- 代码分割:将第三方库分离,提高缓存利用率
- 文件哈希:使用内容哈希命名,支持长期缓存
- 资源内联:小资源内联减少 HTTP 请求
- 目标版本:使用现代 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.js2. 性能问题排查
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 上实现了优秀的性能表现:
- 极快的加载速度:通过缓存策略和 CDN 优化
- 优秀的用户体验:通过性能监控和优化
- 可靠的部署流程:通过 CI/CD 自动化
- 完善的安全防护:通过安全头部配置
- 持续的监控改进:通过数据分析优化
这些优化策略不仅提升了博客的性能和用户体验,也为后续的扩展和维护打下了坚实的基础。部署优化是一个持续的过程,需要根据实际监控数据和用户反馈不断调整和改进。
通过本文的指导,您可以构建出高性能、高可用的 VitePress 博客部署方案,为用户提供优秀的访问体验。