vercel-deployments
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVercel Deployments
Vercel 部署
Ship web apps quickly with preview environments and managed edge infrastructure.
借助预览环境和托管式边缘基础设施,快速部署Web应用。
When to Use This Skill
适用场景
Use this skill when:
- Deploying Next.js, SvelteKit, Nuxt, or static sites
- Setting up preview environments for every PR
- Configuring edge functions and serverless APIs
- Managing environment variables across preview/production
- Setting up custom domains and redirects
在以下场景使用本技能:
- 部署Next.js、SvelteKit、Nuxt或静态站点
- 为每个PR设置预览环境
- 配置Edge Functions和无服务器API
- 在预览/生产环境间管理环境变量
- 设置自定义域名和重定向规则
Prerequisites
前置条件
- Node.js 18+
- Vercel account (free tier works for personal projects)
- Git repository (GitHub, GitLab, or Bitbucket)
- Node.js 18+
- Vercel账号(个人项目可使用免费版)
- Git仓库(GitHub、GitLab或Bitbucket)
Quick Start
快速开始
bash
undefinedbash
undefinedInstall CLI
Install CLI
npm i -g vercel
npm i -g vercel
Login and link project
Login and link project
vercel login
vercel link
vercel login
vercel link
Deploy to preview
Deploy to preview
vercel
vercel
Deploy to production
Deploy to production
vercel --prod
vercel --prod
Pull environment variables locally
Pull environment variables locally
vercel env pull .env.local
undefinedvercel env pull .env.local
undefinedProject Configuration
项目配置
json
// vercel.json
{
"framework": "nextjs",
"buildCommand": "npm run build",
"outputDirectory": ".next",
"installCommand": "npm ci",
"regions": ["iad1", "sfo1", "cdg1"],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "no-store" },
{ "key": "X-Content-Type-Options", "value": "nosniff" }
]
},
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains" }
]
}
],
"redirects": [
{ "source": "/blog/:slug", "destination": "/posts/:slug", "permanent": true }
],
"rewrites": [
{ "source": "/api/v1/:path*", "destination": "https://api.example.com/:path*" }
]
}json
// vercel.json
{
"framework": "nextjs",
"buildCommand": "npm run build",
"outputDirectory": ".next",
"installCommand": "npm ci",
"regions": ["iad1", "sfo1", "cdg1"],
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Cache-Control", "value": "no-store" },
{ "key": "X-Content-Type-Options", "value": "nosniff" }
]
},
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "Strict-Transport-Security", "value": "max-age=63072000; includeSubDomains" }
]
}
],
"redirects": [
{ "source": "/blog/:slug", "destination": "/posts/:slug", "permanent": true }
],
"rewrites": [
{ "source": "/api/v1/:path*", "destination": "https://api.example.com/:path*" }
]
}Environment Variables
环境变量
bash
undefinedbash
undefinedAdd environment variables
Add environment variables
vercel env add DATABASE_URL production
vercel env add DATABASE_URL preview
vercel env add NEXT_PUBLIC_API_URL production
vercel env add DATABASE_URL production
vercel env add DATABASE_URL preview
vercel env add NEXT_PUBLIC_API_URL production
List all env vars
List all env vars
vercel env ls
vercel env ls
Pull to local .env.local
Pull to local .env.local
vercel env pull .env.local
vercel env pull .env.local
Remove an env var
Remove an env var
vercel env rm SECRET_KEY production
undefinedvercel env rm SECRET_KEY production
undefinedEnvironment Separation Pattern
环境隔离模式
bash
undefinedbash
undefinedProduction — real credentials
Production — real credentials
vercel env add DATABASE_URL production <<< "postgresql://prod-host:5432/app"
vercel env add STRIPE_SECRET_KEY production
vercel env add DATABASE_URL production <<< "postgresql://prod-host:5432/app"
vercel env add STRIPE_SECRET_KEY production
Preview — staging/test credentials
Preview — staging/test credentials
vercel env add DATABASE_URL preview <<< "postgresql://staging-host:5432/app"
vercel env add STRIPE_SECRET_KEY preview # Use test mode key
vercel env add DATABASE_URL preview <<< "postgresql://staging-host:5432/app"
vercel env add STRIPE_SECRET_KEY preview # Use test mode key
Development — local values
Development — local values
vercel env add DATABASE_URL development <<< "postgresql://localhost:5432/app"
undefinedvercel env add DATABASE_URL development <<< "postgresql://localhost:5432/app"
undefinedEdge Functions
Edge Functions
typescript
// app/api/geo/route.ts — Edge API route (Next.js App Router)
import { NextRequest } from 'next/server';
export const runtime = 'edge';
export function GET(request: NextRequest) {
const country = request.geo?.country || 'US';
const city = request.geo?.city || 'Unknown';
return Response.json({
country,
city,
region: request.geo?.region,
timestamp: new Date().toISOString(),
});
}typescript
// middleware.ts — Edge middleware for auth/redirects
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
// Block non-US traffic from admin
if (request.nextUrl.pathname.startsWith('/admin')) {
if (request.geo?.country !== 'US') {
return NextResponse.redirect(new URL('/blocked', request.url));
}
}
// Add security headers
const response = NextResponse.next();
response.headers.set('X-Request-Id', crypto.randomUUID());
return response;
}
export const config = {
matcher: ['/admin/:path*', '/api/:path*'],
};typescript
// app/api/geo/route.ts — Edge API route (Next.js App Router)
import { NextRequest } from 'next/server';
export const runtime = 'edge';
export function GET(request: NextRequest) {
const country = request.geo?.country || 'US';
const city = request.geo?.city || 'Unknown';
return Response.json({
country,
city,
region: request.geo?.region,
timestamp: new Date().toISOString(),
});
}typescript
// middleware.ts — Edge middleware for auth/redirects
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
// Block non-US traffic from admin
if (request.nextUrl.pathname.startsWith('/admin')) {
if (request.geo?.country !== 'US') {
return NextResponse.redirect(new URL('/blocked', request.url));
}
}
// Add security headers
const response = NextResponse.next();
response.headers.set('X-Request-Id', crypto.randomUUID());
return response;
}
export const config = {
matcher: ['/admin/:path*', '/api/:path*'],
};GitHub Actions Integration
GitHub Actions 集成
yaml
undefinedyaml
undefined.github/workflows/preview.yml
.github/workflows/preview.yml
name: Vercel Preview
on: pull_request
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test
- name: Deploy to Vercel Preview
id: deploy
run: |
npm i -g vercel
URL=$(vercel --token ${{ secrets.VERCEL_TOKEN }} --yes)
echo "url=$URL" >> "$GITHUB_OUTPUT"
- name: Comment PR with preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Preview deployed: ${{ steps.deploy.outputs.url }}`
});undefinedname: Vercel Preview
on: pull_request
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run test
- name: Deploy to Vercel Preview
id: deploy
run: |
npm i -g vercel
URL=$(vercel --token ${{ secrets.VERCEL_TOKEN }} --yes)
echo "url=$URL" >> "$GITHUB_OUTPUT"
- name: Comment PR with preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `Preview deployed: ${{ steps.deploy.outputs.url }}`
});undefinedCLI Commands Reference
CLI命令参考
bash
undefinedbash
undefinedDeployments
Deployments
vercel # Deploy to preview
vercel --prod # Deploy to production
vercel rollback # Rollback last production deploy
vercel promote <url> # Promote preview to production
vercel # Deploy to preview
vercel --prod # Deploy to production
vercel rollback # Rollback last production deploy
vercel promote <url> # Promote preview to production
Domains
Domains
vercel domains add example.com
vercel domains ls
vercel certs ls
vercel domains add example.com
vercel domains ls
vercel certs ls
Logs
Logs
vercel logs <deployment-url>
vercel logs <deployment-url> --follow
vercel logs <deployment-url>
vercel logs <deployment-url> --follow
Project management
Project management
vercel project ls
vercel project rm <name>
vercel project ls
vercel project rm <name>
Inspect deployment
Inspect deployment
vercel inspect <deployment-url>
undefinedvercel inspect <deployment-url>
undefinedProduction Guardrails
生产环境防护机制
- Require preview checks before merge (GitHub branch protection)
- Separate preview and production environment variables — never share API keys
- Use branch protection with required deployment status checks
- Monitor function duration and cold start behavior in Vercel Analytics
- Set spend limits in Vercel dashboard to prevent cost surprises
- Enable Vercel Firewall for DDoS and bot protection
- Use headers for security (CSP, HSTS, X-Frame-Options)
vercel.json
- 合并前要求通过预览检查(GitHub分支保护)
- 隔离预览与生产环境变量——绝不共享API密钥
- 启用分支保护并设置必需的部署状态检查
- 在Vercel Analytics中监控函数执行时长和冷启动情况
- 在Vercel控制台设置消费限额,避免意外支出
- 启用Vercel Firewall以防护DDoS和机器人攻击
- 使用配置安全头(CSP、HSTS、X-Frame-Options)
vercel.json
Monitoring & Analytics
监控与分析
bash
undefinedbash
undefinedEnable Speed Insights in Next.js
Enable Speed Insights in Next.js
npm install @vercel/speed-insights
npm install @vercel/speed-insights
Enable Web Analytics
Enable Web Analytics
npm install @vercel/analytics
```typescript
// app/layout.tsx
import { Analytics } from '@vercel/analytics/react';
import { SpeedInsights } from '@vercel/speed-insights/next';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics />
<SpeedInsights />
</body>
</html>
);
}npm install @vercel/analytics
```typescript
// app/layout.tsx
import { Analytics } from '@vercel/analytics/react';
import { SpeedInsights } from '@vercel/speed-insights/next';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<Analytics />
<SpeedInsights />
</body>
</html>
);
}Troubleshooting
故障排查
| Issue | Solution |
|---|---|
| Build fails | Check |
| Env vars missing | Run |
| Edge function timeout | Edge has 30s limit; move heavy work to serverless (no |
| Cold starts slow | Use edge runtime where possible, reduce bundle size |
| Domain not working | Check DNS propagation, verify |
| 问题 | 解决方案 |
|---|---|
| 构建失败 | 查看 |
| 环境变量缺失 | 执行 |
| Edge Function超时 | Edge运行时限制为30秒;将繁重任务迁移至无服务器函数(不设置 |
| 冷启动缓慢 | 尽可能使用Edge运行时,减小包体积 |
| 域名无法正常工作 | 检查DNS解析状态,验证 |
Related Skills
相关技能
- github-actions — Automated deployment gates
- cloudflare-pages — Alternative edge hosting
- ssl-tls-management — Custom certificate setup
- github-actions — 自动化部署网关
- cloudflare-pages — 可选边缘托管服务
- ssl-tls-management — 自定义证书配置