vercel-deployments

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Vercel 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
undefined
bash
undefined

Install 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
undefined
vercel env pull .env.local
undefined

Project 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
undefined
bash
undefined

Add 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
undefined
vercel env rm SECRET_KEY production
undefined

Environment Separation Pattern

环境隔离模式

bash
undefined
bash
undefined

Production — 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"
undefined
vercel env add DATABASE_URL development <<< "postgresql://localhost:5432/app"
undefined

Edge 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
undefined
yaml
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 }}`
        });
undefined
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 }}`
        });
undefined

CLI Commands Reference

CLI命令参考

bash
undefined
bash
undefined

Deployments

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>
undefined
vercel inspect <deployment-url>
undefined

Production 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
    vercel.json
    headers for security (CSP, HSTS, X-Frame-Options)
  • 合并前要求通过预览检查(GitHub分支保护)
  • 隔离预览与生产环境变量——绝不共享API密钥
  • 启用分支保护并设置必需的部署状态检查
  • 在Vercel Analytics中监控函数执行时长和冷启动情况
  • 在Vercel控制台设置消费限额,避免意外支出
  • 启用Vercel Firewall以防护DDoS和机器人攻击
  • 使用
    vercel.json
    配置安全头(CSP、HSTS、X-Frame-Options)

Monitoring & Analytics

监控与分析

bash
undefined
bash
undefined

Enable 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

故障排查

IssueSolution
Build failsCheck
vercel logs
, verify Node.js version in
engines
field
Env vars missingRun
vercel env pull
, check variable scope (preview vs production)
Edge function timeoutEdge has 30s limit; move heavy work to serverless (no
runtime = 'edge'
)
Cold starts slowUse edge runtime where possible, reduce bundle size
Domain not workingCheck DNS propagation, verify
vercel domains
configuration
问题解决方案
构建失败查看
vercel logs
,验证
engines
字段中的Node.js版本
环境变量缺失执行
vercel env pull
,检查变量作用域(预览 vs 生产)
Edge Function超时Edge运行时限制为30秒;将繁重任务迁移至无服务器函数(不设置
runtime = 'edge'
冷启动缓慢尽可能使用Edge运行时,减小包体积
域名无法正常工作检查DNS解析状态,验证
vercel domains
配置

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 — 自定义证书配置