mcpField
N
nextjs

nextjs

github.com/thelobbi开发2150 次安装6 天前更新
代码仓库

关于 nextjs

nextjs 是面向现代 Web 应用开发的 Next.js 技能,适用于使用 App Router 构建页面和服务端功能的开发者。内容包括组件、数据获取、Server Actions、API 路由和中间件。

主要功能

  1. 01App Router 页面与布局
  2. 02服务端和客户端组件
  3. 03数据获取与缓存再验证
  4. 04Server Actions 与 API 路由
  5. 05中间件和环境变量管理

适用场景

  1. 01构建带加载与错误状态的页面
  2. 02从服务端获取并缓存数据
  3. 03通过 Server Actions 更新数据
  4. 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'

评论

支持 Markdown