npx skills add https://github.com/awais68/phase-5-cloud-deployment --skill vercel-deploy精通将 Next.js 应用程序部署到 Vercel,提供最优构建设置、环境配置和自定义域名设置。
| 任务 | 文件/命令 |
|---|---|
| 配置构建 | vercel.json |
| 设置环境变量 | Vercel 仪表板或 CLI |
| 部署 | vercel --prod |
| 检查状态 | vercel inspect |
| 自定义域名 | Vercel 仪表板 > 设置 > 域名 |
project/
├── vercel.json # Vercel 配置
├── next.config.js # Next.js 配置
├── .env.local # 本地开发(不提交)
├── .env.example # 模板(提交)
├── docs/
│ └── deployment.md # 部署文档
└── frontend/ # Next.js 应用
├── app/
├── public/
└── src/
Expert deployment of Next.js applications to Vercel with optimal build settings, environment configuration, and custom domain setup.
| Task | File/Command |
|---|---|
| Configure build | vercel.json |
| Set env vars | Vercel Dashboard or CLI |
| Deploy | vercel --prod |
| Check status | vercel inspect |
| Custom domain | Vercel Dashboard > Settings > Domains |
project/
├── vercel.json # Vercel configuration
├── next.config.js # Next.js configuration
├── .env.local # Local development (not committed)
├── .env.example # Template (committed)
├── docs/
│ └── deployment.md # Deployment documentation
└── frontend/ # Next.js app
├── app/
├── public/
└── src/
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
{
"buildCommand": "npm run build",
"outputDirectory": ".next",
"installCommand": "npm install",
"framework": "nextjs",
"regions": ["iad1"],
"env": {
"NEXT_PUBLIC_API_URL": "@api_url"
}
}
{
"version": 2,
"buildCommand": "npm run build",
"outputDirectory": ".next",
"installCommand": "npm install",
"framework": "nextjs",
"regions": ["iad1"],
"rewrites": [
{
"source": "/api/:path*",
"destination": "https://api.yourdomain.com/:path*"
}
],
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-XSS-Protection",
"value": "1; mode=block"
}
]
},
{
"source": "/static/:path*",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
},
{
"source": "/api/:path*",
"headers": [
{
"key": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
],
"redirects": [
{
"source": "/old-path/:path*",
"destination": "/new-path/:path*",
"permanent": true
},
{
"source": "/www/:path*",
"destination": "/:path*",
"permanent": true
}
]
}
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
// Vercel 的输出配置
output: 'standalone',
// 图片优化
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'api.yourdomain.com',
pathname: '/uploads/**',
},
],
formats: ['image/avif', 'image/webp'],
},
// 安全相关的响应头
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'X-DNS-Prefetch-Control',
value: 'on',
},
{
key: 'Referrer-Policy',
value: 'origin-when-cross-origin',
},
],
},
];
},
// 重定向
async redirects() {
return [
{
source: '/legacy/:path*',
destination: '/:path*',
permanent: true,
},
];
},
// 实验性功能
experimental: {
serverActions: {
allowedOrigins: ['yourdomain.com'],
},
},
};
module.exports = nextConfig;
| 前缀 | 访问权限 | 描述 |
|---|---|---|
NEXT_PUBLIC_ | 客户端 + 服务器 | 暴露给浏览器 |
| 无前缀 | 仅服务器 | 仅限后端/API 使用 |
# .env.example - 复制到 .env.local 用于本地开发
# API 配置
# 后端 API URL(开发环境)
NEXT_PUBLIC_API_URL="http://localhost:8000/api/v1"
# 身份验证
NEXT_PUBLIC_AUTH_ENABLED="true"
# 功能开关
NEXT_PUBLIC_ENABLE_DARK_MODE="true"
NEXT_PUBLIC_SHOW_BETA_FEATURES="false"
# 生产环境变量
# API 配置
NEXT_PUBLIC_API_URL="https://api.yourdomain.com"
# 可选:分析
NEXT_PUBLIC_GA_ID="G-XXXXXXXXXX"
NEXT_PUBLIC_POSTHOG_KEY="phc_xxx"
# 可选:错误追踪
NEXT_PUBLIC_SENTRY_DSN="https://xxx@sentry.io/xxx"
这些变量不应有 NEXT_PUBLIC_ 前缀:
# 仅限服务器(绝不暴露给客户端)
API_SECRET_KEY="vercel-secret-key"
DATABASE_URL="postgresql://..."
REDIS_URL="redis://..."
# 安装 Vercel CLI
npm i -g vercel
# 登录 Vercel
vercel login
# 链接到项目
cd frontend
vercel link
# 部署到预览环境(暂存)
vercel
# 部署到生产环境
vercel --prod
# 带环境变量部署
vercel --env=NODE_ENV=production
# 从 Vercel 拉取环境变量
vercel env pull .env.local
# 在 CI 流水线中
npm i -g vercel
vercel --token=$VERCEL_TOKEN --yes
yourdomain.com)# 对于根域名(yourdomain.com)
类型: A
名称: @
值: 76.76.21.21
# 对于 www 子域名
类型: CNAME
名称: www
值: cname.vercel-dns.com.
# 对于 API 子域名(可选)
类型: CNAME
名称: api
值: cname.vercel-dns.com.
{
"redirects": [
{
"source": "/:path*",
"destination": "https://yourdomain.com/:path*",
"permanent": true
}
]
}
{
"rewrites": [
{
"source": "/api/:path*",
"destination": "https://api.yourdomain.com/:path*"
}
]
}
// next.config.js
async rewrites() {
return [
{
source: '/api/:path*',
destination: `${process.env.NEXT_PUBLIC_API_URL}/:path*`,
},
];
}
// frontend/app/api/[...route]/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/endpoint`,
{
headers: {
'Authorization': request.headers.get('Authorization') || '',
'Content-Type': 'application/json',
},
}
);
const data = await response.json();
return NextResponse.json(data);
}
# 标准构建
npm run build
# 仅进行 TypeScript 检查
npm run build -- --no-lint
# 自定义构建
next build
// next.config.js
const nextConfig = {
// 启用 SWC 压缩器(构建更快)
swcMinify: true,
// 编译器选项
compiler: {
removeConsole: process.env.NODE_ENV === 'production',
},
// 图片优化
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
// 启用 React 严格模式
reactStrictMode: true,
// 生成 Etag
generateEtags: true,
};
# 安装包分析器
npm install -D @next/bundle-analyzer
# next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
// 你的配置
});
// frontend/app/not-found.tsx
import Link from 'next/link';
export default function NotFound() {
return (
<div className="min-h-screen flex flex-col items-center justify-center">
<h1 className="text-4xl font-bold">404 - 页面未找到</h1>
<p className="mt-2 text-gray-600">
您查找的页面不存在。
</p>
<Link
href="/"
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded"
>
返回首页
</Link>
</div>
);
}
// frontend/app/error.tsx
'use client';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div className="min-h-screen flex flex-col items-center justify-center">
<h1 className="text-4xl font-bold">出错了!</h1>
<p className="mt-2 text-gray-600">
发生了一个意外错误。
</p>
<button
onClick={() => reset()}
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded"
>
重试
</button>
</div>
);
}
// frontend/app/global-error.tsx
'use client';
export default function GlobalError({
error,
}: {
error: Error & { digest?: string };
}) {
return (
<html>
<body>
<div className="min-h-screen flex items-center justify-center">
<h1 className="text-2xl">应用程序错误</h1>
</div>
</body>
</html>
);
}
npm run build 无错误完成NEXT_PUBLIC_ 前缀# 部署指南
## 快速部署
[](https://vercel.com/new)
## 环境变量
### 开发环境
```bash
NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
yourdomain.com@ -> 76.76.21.21www -> cname.vercel-dns.com# 本地运行以查看错误
npm run build
NEXT_PUBLIC_ 开头验证 vercel.json 中的 outputDirectory 是否与构建输出匹配
检查页面文件是否在 app/ 目录中(App Router)
| 技能 | 集成 |
|---|---|
@frontend-nextjs-app-router | Next.js App Router 配置 |
@env-config | 环境变量管理 |
@tailwind-css | CSS 构建优化 |
@api-route-design | API 路由和重写 |
@error-handling | 自定义错误页面 |
每周安装数
1
代码仓库
首次出现
1 天前
安全审计
安装在
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1
{
"buildCommand": "npm run build",
"outputDirectory": ".next",
"installCommand": "npm install",
"framework": "nextjs",
"regions": ["iad1"],
"env": {
"NEXT_PUBLIC_API_URL": "@api_url"
}
}
{
"version": 2,
"buildCommand": "npm run build",
"outputDirectory": ".next",
"installCommand": "npm install",
"framework": "nextjs",
"regions": ["iad1"],
"rewrites": [
{
"source": "/api/:path*",
"destination": "https://api.yourdomain.com/:path*"
}
],
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-Frame-Options",
"value": "DENY"
},
{
"key": "X-XSS-Protection",
"value": "1; mode=block"
}
]
},
{
"source": "/static/:path*",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
},
{
"source": "/api/:path*",
"headers": [
{
"key": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
],
"redirects": [
{
"source": "/old-path/:path*",
"destination": "/new-path/:path*",
"permanent": true
},
{
"source": "/www/:path*",
"destination": "/:path*",
"permanent": true
}
]
}
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
// Output configuration for Vercel
output: 'standalone',
// Image optimization
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'api.yourdomain.com',
pathname: '/uploads/**',
},
],
formats: ['image/avif', 'image/webp'],
},
// Headers for security
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'X-DNS-Prefetch-Control',
value: 'on',
},
{
key: 'Referrer-Policy',
value: 'origin-when-cross-origin',
},
],
},
];
},
// Redirects
async redirects() {
return [
{
source: '/legacy/:path*',
destination: '/:path*',
permanent: true,
},
];
},
// Experimental features
experimental: {
serverActions: {
allowedOrigins: ['yourdomain.com'],
},
},
};
module.exports = nextConfig;
| Prefix | Access | Description |
|---|---|---|
NEXT_PUBLIC_ | Client + Server | Exposed to browser |
| No prefix | Server only | Backend/API use only |
# .env.example - Copy to .env.local for local dev
# API Configuration
# Backend API URL (development)
NEXT_PUBLIC_API_URL="http://localhost:8000/api/v1"
# Authentication
NEXT_PUBLIC_AUTH_ENABLED="true"
# Feature Flags
NEXT_PUBLIC_ENABLE_DARK_MODE="true"
NEXT_PUBLIC_SHOW_BETA_FEATURES="false"
# Environment variables for Production
# API Configuration
NEXT_PUBLIC_API_URL="https://api.yourdomain.com"
# Optional: Analytics
NEXT_PUBLIC_GA_ID="G-XXXXXXXXXX"
NEXT_PUBLIC_POSTHOG_KEY="phc_xxx"
# Optional: Error tracking
NEXT_PUBLIC_SENTRY_DSN="https://xxx@sentry.io/xxx"
These should NOT have NEXT_PUBLIC_ prefix:
# Server-only (never exposed to client)
API_SECRET_KEY="vercel-secret-key"
DATABASE_URL="postgresql://..."
REDIS_URL="redis://..."
# Install Vercel CLI
npm i -g vercel
# Login to Vercel
vercel login
# Link to project
cd frontend
vercel link
# Deploy to preview (staging)
vercel
# Deploy to production
vercel --prod
# Deploy with environment
vercel --env=NODE_ENV=production
# Pull environment variables from Vercel
vercel env pull .env.local
# In CI pipeline
npm i -g vercel
vercel --token=$VERCEL_TOKEN --yes
yourdomain.com)# For root domain (yourdomain.com)
Type: A
Name: @
Value: 76.76.21.21
# For www subdomain
Type: CNAME
Name: www
Value: cname.vercel-dns.com.
# For API subdomain (optional)
Type: CNAME
Name: api
Value: cname.vercel-dns.com.
{
"redirects": [
{
"source": "/:path*",
"destination": "https://yourdomain.com/:path*",
"permanent": true
}
]
}
{
"rewrites": [
{
"source": "/api/:path*",
"destination": "https://api.yourdomain.com/:path*"
}
]
}
// next.config.js
async rewrites() {
return [
{
source: '/api/:path*',
destination: `${process.env.NEXT_PUBLIC_API_URL}/:path*`,
},
];
}
// frontend/app/api/[...route]/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/endpoint`,
{
headers: {
'Authorization': request.headers.get('Authorization') || '',
'Content-Type': 'application/json',
},
}
);
const data = await response.json();
return NextResponse.json(data);
}
# Standard build
npm run build
# With TypeScript check only
npm run build -- --no-lint
# Custom build
next build
// next.config.js
const nextConfig = {
// Enable SWC minifier (faster builds)
swcMinify: true,
// Compiler options
compiler: {
removeConsole: process.env.NODE_ENV === 'production',
},
// Image optimization
images: {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
},
// Enable react strict mode
reactStrictMode: true,
// Generate Etag
generateEtags: true,
};
# Install bundle analyzer
npm install -D @next/bundle-analyzer
# next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withBundleAnalyzer({
// your config
});
// frontend/app/not-found.tsx
import Link from 'next/link';
export default function NotFound() {
return (
<div className="min-h-screen flex flex-col items-center justify-center">
<h1 className="text-4xl font-bold">404 - Page Not Found</h1>
<p className="mt-2 text-gray-600">
The page you're looking for doesn't exist.
</p>
<Link
href="/"
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded"
>
Go Home
</Link>
</div>
);
}
// frontend/app/error.tsx
'use client';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div className="min-h-screen flex flex-col items-center justify-center">
<h1 className="text-4xl font-bold">Something went wrong!</h1>
<p className="mt-2 text-gray-600">
An unexpected error occurred.
</p>
<button
onClick={() => reset()}
className="mt-4 px-4 py-2 bg-blue-600 text-white rounded"
>
Try Again
</button>
</div>
);
}
// frontend/app/global-error.tsx
'use client';
export default function GlobalError({
error,
}: {
error: Error & { digest?: string };
}) {
return (
<html>
<body>
<div className="min-h-screen flex items-center justify-center">
<h1 className="text-2xl">Application Error</h1>
</div>
</body>
</html>
);
}
npm run build completes without errorsNEXT_PUBLIC_ prefix on secrets# Deployment Guide
## Quick Deploy
[](https://vercel.com/new)
## Environment Variables
### Development
```bash
NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
yourdomain.com in Vercel Dashboard > Settings > Domains@ -> 76.76.21.21www -> cname.vercel-dns.com# Run locally to see error
npm run build
NEXT_PUBLIC_ for client accessVerify vercel.json outputDirectory matches build output
Check page files are in app/ directory (App Router)
| Skill | Integration |
|---|---|
@frontend-nextjs-app-router | Next.js App Router configuration |
@env-config | Environment variable management |
@tailwind-css | CSS build optimization |
@api-route-design | API routes and rewrites |
@error-handling | Custom error pages |
Weekly Installs
1
Repository
First Seen
1 day ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1