name: vercel description: 在Vercel上部署和配置应用程序。用于部署Next.js应用、配置服务器less函数、设置边缘函数或管理Vercel项目。触发词:Vercel、deploy、serverless、edge function、Next.js deployment。
Vercel部署
在Vercel的边缘网络上部署和扩展应用程序。
快速开始
# 安装Vercel CLI
npm i -g vercel
# 部署
vercel
# 生产环境部署
vercel --prod
vercel.json配置
{
"buildCommand": "npm run build",
"outputDirectory": ".next",
"framework": "nextjs",
"regions": ["iad1", "sfo1"],
"functions": {
"api/**/*.ts": {
"memory": 1024,
"maxDuration": 30
}
},
"rewrites": [
{ "source": "/api/:path*", "destination": "/api/:path*" },
{ "source": "/:path*", "destination": "/" }
],
"headers": [
{
"source": "/api/:path*",
"headers": [
{ "key": "Access-Control-Allow-Origin", "value": "*" }
]
}
],
"env": {
"DATABASE_URL": "@database-url"
}
}
服务器less函数
// api/hello.ts
import type { VercelRequest, VercelResponse } from '@vercel/node';
export default function handler(req: VercelRequest, res: VercelResponse) {
const { name = 'World' } = req.query;
res.status(200).json({ message: `Hello ${name}!` });
}
边缘函数
// api/edge.ts
export const config = {
runtime: 'edge',
};
export default function handler(request: Request) {
return new Response(JSON.stringify({ message: 'Hello from Edge!' }), {
headers: { 'content-type': 'application/json' },
});
}
Next.js应用路由器
// app/api/route.ts
import { NextResponse } from 'next/server';
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const name = searchParams.get('name') ?? 'World';
return NextResponse.json({ message: `Hello ${name}!` });
}
export async function POST(request: Request) {
const body = await request.json();
return NextResponse.json({ received: body });
}
ISR(增量静态再生)
// app/posts/[id]/page.tsx
export const revalidate = 60; // 每60秒重新验证
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({ id: post.id }));
}
export default async function Post({ params }: { params: { id: string } }) {
const post = await getPost(params.id);
return <article>{post.content}</article>;
}
Vercel KV(Redis)
import { kv } from '@vercel/kv';
// 设置
await kv.set('user:123', { name: 'Alice', visits: 0 });
// 获取
const user = await kv.get('user:123');
// 递增
await kv.incr('user:123:visits');
// 哈希操作
await kv.hset('session:abc', { userId: '123', expires: Date.now() + 3600000 });
const session = await kv.hgetall('session:abc');
Vercel Postgres
import { sql } from '@vercel/postgres';
// 查询
const { rows } = await sql`SELECT * FROM users WHERE id = ${userId}`;
// 插入
await sql`INSERT INTO users (name, email) VALUES (${name}, ${email})`;
// 事务
await sql.query('BEGIN');
try {
await sql`UPDATE accounts SET balance = balance - ${amount} WHERE id = ${from}`;
await sql`UPDATE accounts SET balance = balance + ${amount} WHERE id = ${to}`;
await sql.query('COMMIT');
} catch (e) {
await sql.query('ROLLBACK');
throw e;
}
环境变量
# 添加秘密
vercel env add DATABASE_URL production
# 本地拉取环境变量
vercel env pull .env.local
# 列出环境变量
vercel env ls
Cron作业
// vercel.json
{
"crons": [
{
"path": "/api/daily-job",
"schedule": "0 0 * * *"
}
]
}
// api/daily-job.ts
export default function handler(req, res) {
// 验证来自Vercel Cron
if (req.headers['authorization'] !== `Bearer ${process.env.CRON_SECRET}`) {
return res.status(401).end();
}
// 运行作业
await runDailyJob();
res.status(200).end();
}
资源
- Vercel文档: https://vercel.com/docs
- Next.js on Vercel: https://vercel.com/docs/frameworks/nextjs