vercel
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVercel Deployment
Vercel 部署
Deploy and scale applications on Vercel's edge network.
在Vercel的边缘网络上部署和扩展应用程序。
Quick Start
快速开始
bash
undefinedbash
undefinedInstall Vercel CLI
Install Vercel CLI
npm i -g vercel
npm i -g vercel
Deploy
Deploy
vercel
vercel
Production deploy
Production deploy
vercel --prod
undefinedvercel --prod
undefinedvercel.json Configuration
vercel.json 配置
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"
}
}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"
}
}Serverless Functions
Serverless 函数
typescript
// 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}!` });
}typescript
// 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}!` });
}Edge Functions
Edge 函数
typescript
// 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' },
});
}typescript
// 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 Router
Next.js App Router
typescript
// 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 });
}typescript
// 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 (Incremental Static Regeneration)
ISR(增量静态再生)
typescript
// app/posts/[id]/page.tsx
export const revalidate = 60; // Revalidate every 60 seconds
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>;
}typescript
// app/posts/[id]/page.tsx
export const revalidate = 60; // Revalidate every 60 seconds
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)
Vercel KV(Redis)
typescript
import { kv } from '@vercel/kv';
// Set
await kv.set('user:123', { name: 'Alice', visits: 0 });
// Get
const user = await kv.get('user:123');
// Increment
await kv.incr('user:123:visits');
// Hash operations
await kv.hset('session:abc', { userId: '123', expires: Date.now() + 3600000 });
const session = await kv.hgetall('session:abc');typescript
import { kv } from '@vercel/kv';
// Set
await kv.set('user:123', { name: 'Alice', visits: 0 });
// Get
const user = await kv.get('user:123');
// Increment
await kv.incr('user:123:visits');
// Hash operations
await kv.hset('session:abc', { userId: '123', expires: Date.now() + 3600000 });
const session = await kv.hgetall('session:abc');Vercel Postgres
Vercel Postgres
typescript
import { sql } from '@vercel/postgres';
// Query
const { rows } = await sql`SELECT * FROM users WHERE id = ${userId}`;
// Insert
await sql`INSERT INTO users (name, email) VALUES (${name}, ${email})`;
// Transaction
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;
}typescript
import { sql } from '@vercel/postgres';
// Query
const { rows } = await sql`SELECT * FROM users WHERE id = ${userId}`;
// Insert
await sql`INSERT INTO users (name, email) VALUES (${name}, ${email})`;
// Transaction
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;
}Environment Variables
环境变量
bash
undefinedbash
undefinedAdd secret
Add secret
vercel env add DATABASE_URL production
vercel env add DATABASE_URL production
Pull env vars locally
Pull env vars locally
vercel env pull .env.local
vercel env pull .env.local
List env vars
List env vars
vercel env ls
undefinedvercel env ls
undefinedCron Jobs
定时任务(Cron Jobs)
json
// vercel.json
{
"crons": [
{
"path": "/api/daily-job",
"schedule": "0 0 * * *"
}
]
}typescript
// api/daily-job.ts
export default function handler(req, res) {
// Verify it's from Vercel Cron
if (req.headers['authorization'] !== `Bearer ${process.env.CRON_SECRET}`) {
return res.status(401).end();
}
// Run job
await runDailyJob();
res.status(200).end();
}json
// vercel.json
{
"crons": [
{
"path": "/api/daily-job",
"schedule": "0 0 * * *"
}
]
}typescript
// api/daily-job.ts
export default function handler(req, res) {
// Verify it's from Vercel Cron
if (req.headers['authorization'] !== `Bearer ${process.env.CRON_SECRET}`) {
return res.status(401).end();
}
// Run job
await runDailyJob();
res.status(200).end();
}Resources
资源
- Vercel Docs: https://vercel.com/docs
- Next.js on Vercel: https://vercel.com/docs/frameworks/nextjs
- Vercel 文档: https://vercel.com/docs
- Vercel 上的 Next.js: https://vercel.com/docs/frameworks/nextjs