关于 nextjs
nextjs 是面向现代 Web 应用开发的 Next.js 技能,适用于使用 App Router 构建页面和服务端功能的开发者。内容包括组件、数据获取、Server Actions、API 路由和中间件。
主要功能
- 01App Router 页面与布局
- 02服务端和客户端组件
- 03数据获取与缓存再验证
- 04Server Actions 与 API 路由
- 05中间件和环境变量管理
适用场景
- 01构建带加载与错误状态的页面
- 02从服务端获取并缓存数据
- 03通过 Server Actions 更新数据
- 04为路由添加认证检查和响应头
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ thelobbi/ claude --skill nextjs安装后在 Claude Code 中输入/nextjs确认已加载。
详细介绍
Next.js 技能
为现代 Web 应用提供全面的 Next.js 开发能力。
何时使用此技能
在以下场景中启用此技能:
- Next.js App Router
- Server Components 和 Client Components
- API 路由和 Server Actions
- 静态站点生成(SSG)
- 服务器端渲染(SSR)
项目结构(App Router)
``` app/ ├── layout.tsx # 根布局 ├── page.tsx # 首页 ├── loading.tsx # 加载 UI ├── error.tsx # 错误处理 ├── not-found.tsx # 404 页面 ├── globals.css ├── agents/ │ ├── page.tsx # /agents │ ├── [id]/ │ │ ├── page.tsx # /agents/[id] │ │ └── edit/ │ │ └── page.tsx # /agents/[id]/edit │ └── new/ │ └── page.tsx # /agents/new ├── api/ │ └── agents/ │ ├── route.ts # /api/agents │ └── [id]/ │ └── route.ts # /api/agents/[id] └── (dashboard)/ # 路由组 ├── layout.tsx └── settings/ └── page.tsx ```
Server Components(默认)
```tsx // app/agents/page.tsx - Server Component async function AgentsPage() { // 直接访问数据库(无需 API) const agents = await db.query('SELECT * FROM agents');
return (
Agent 列表
-
{agents.map(agent => (
- {agent.name} ))}
export default AgentsPage; ```
Client Components
```tsx // components/AgentSelector.tsx 'use client';
import { useState } from 'react';
export function AgentSelector({ agents }: { agents: Agent[] }) { const [selected, setSelected] = useState<string | null>(null);
return ( <select value={selected || ''} onChange={(e) => setSelected(e.target.value)} > 选择一个 Agent {agents.map(agent => ( {agent.name} ))} ); } ```
数据获取
Server Component 数据获取
```tsx
// 自动对请求去重
async function getAgent(id: string) {
const res = await fetch(${process.env.API_URL}/agents/${id}, {
cache: 'force-cache', // 默认:永久缓存
// cache: 'no-store', // 从不缓存
// next: { revalidate: 60 } // 每 60 秒重新验证
});
return res.json();
}
export default async function AgentPage({ params }: { params: { id: string } }) { const agent = await getAgent(params.id); return ; } ```
重新验证
```tsx // 基于时间的重新验证 export const revalidate = 60; // 每 60 秒重新验证
// 按需重新验证 import { revalidatePath, revalidateTag } from 'next/cache';
async function updateAgent(id: string, data: FormData) { 'use server'; await db.update('agents', id, data); revalidatePath('/agents'); revalidateTag('agents'); } ```
Server Actions
```tsx // app/agents/new/page.tsx import { redirect } from 'next/navigation';
async function createAgent(formData: FormData) { 'use server';
const name = formData.get('name') as string; const type = formData.get('type') as string;
await db.insert('agents', { name, type });
revalidatePath('/agents'); redirect('/agents'); }
export default function NewAgentPage() { return (
Claude GPT 创建 Agent ); } ```API 路由
// app/api/agents/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const type = searchParams.get('type');
const agents = await db.query(
'SELECT * FROM agents WHERE type = $1',
[type]
);
return NextResponse.json(agents);
}
export async function POST(request: NextRequest) {
const body = await request.json();
const agent = await db.insert('agents', body);
return NextResponse.json(agent, { status: 201 });
}
// app/api/agents/[id]/route.ts
export async function GET(
request: NextRequest,
{ params }: { params: { id: string } }
) {
const agent = await db.query('SELECT * FROM agents WHERE id = $1', [params.id]);
if (!agent) {
return NextResponse.json({ error: '未找到' }, { status: 404 });
}
return NextResponse.json(agent);
}
布局和加载状态
// app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<nav>导航</nav>
<main>{children}</main>
<footer>页脚</footer>
</body>
</html>
);
}
// app/agents/loading.tsx
export default function Loading() {
return <div className="spinner">正在加载 Agent...</div>;
}
// app/agents/error.tsx
'use client';
export default function Error({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return (
<div>
<h2>出了点问题!</h2>
<button onClick={() => reset()}>重试</button>
</div>
);
}
中间件
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
// 身份验证检查
const token = request.cookies.get('token');
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
// 添加标头
const response = NextResponse.next();
response.headers.set('x-custom-header', 'value');
return response;
}
export const config = {
matcher: ['/dashboard/:path*', '/api/:path*'],
};
环境变量
# .env.local
DATABASE_URL=postgresql://...
API_URL=http://localhost:8000
# 公共变量(会暴露给浏览器)
NEXT_PUBLIC_APP_URL=http://localhost:3000
// 仅限服务器端
const dbUrl = process.env.DATABASE_URL;
// 客户端可访问
const appUrl = process.env.NEXT_PUBLIC_APP_URL;
构建命令
# 开发
npm run dev
# 生产构建
npm run build
npm start
# 静态导出
npm run build
# next.config.js: output: 'export'