Next.js:React 流行框架的 La Guía Definitiva
Next.js 可以转换成流行的 React 框架,用于构建现代 Web 应用程序。结合 Lado del Servidor (SSR) 渲染、生成和开发体验,Next.js 需要构建 Web 应用程序可扩展和高级版本。
什么是 Next.js?
主要特征
普里梅罗斯帕索斯
创建项目
npx create-next-app@latest mi-proyecto cd mi-proyecto npm run dev
项目结构
├── app/ │ ├── layout.tsx │ ├── page.tsx │ └── globals.css ├── public/ │ └── images/ ├── components/ │ └── ui/ ├── lib/ ├── next.config.js └── package.json
Next.js 14 中的路由
基本页面
// app/page.tsx export default function Home() { return (); } Bienvenidos a Next.js
动态路线
// app/blog/[slug]/page.tsx export default function BlogPost({ params }: { params: { slug: string } }) { return (); }
共享布局
// app/layout.tsx import { Inter } from 'next/font/google'; const inter = Inter({ subsets: ['latin'] }); export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( {children} ); }
数据获取
服务器组件
// app/posts/page.tsx async function getPosts() { const res = await fetch('https://api.ejemplo.com/posts', { next: { revalidate: 3600 } // Revalidar cada hora }); return res.json(); } export default async function Posts() { const posts = await getPosts(); return ({posts.map(post => (); }))} {post.title}
{post.excerpt}
静态生成
// app/posts/[id]/page.tsx export async function generateStaticParams() { const posts = await getPosts(); return posts.map((post) => ({ id: post.id.toString(), })); } export default async function Post({ params }: { params: { id: string } }) { const post = await getPost(params.id); return (); } {post.title}
{post.content}
API 路由
// app/api/posts/route.ts import { NextResponse } from 'next/server'; export async function GET() { try { const posts = await getPosts(); return NextResponse.json(posts); } catch (error) { return NextResponse.json( { error: 'Error al obtener posts' }, { status: 500 } ); } } export async function POST(request: Request) { try { const data = await request.json(); const newPost = await createPost(data); return NextResponse.json(newPost, { status: 201 }); } catch (error) { return NextResponse.json( { error: 'Error al crear post' }, { status: 500 } ); } }
优化
图片
import Image from 'next/image'; export default function Profile() { return (); }
字体
import { Roboto } from 'next/font/google'; const roboto = Roboto({ weight: ['400', '700'], subsets: ['latin'], display: 'swap', }); export default function Layout({ children }) { return ({children}); }
马内霍·德埃斯塔多
客户端组件
'use client'; import { useState } from 'react'; export default function Counter() { const [count, setCount] = useState(0); return (); }Contador: {count}
建立
CSS 模块
// components/Button.tsx import styles from './Button.module.css'; export default function Button({ children }) { return ( ); }
Tailwind CSS
export default function Card({ title, content }) { return (); }{title}{content}
中间件
// middleware.ts import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { // Verificar autenticación const token = request.cookies.get('token'); if (!token) { return NextResponse.redirect(new URL('/login', request.url)); } return NextResponse.next(); } export const config = { matcher: '/dashboard/:path*', };
测试
// __tests__/Home.test.tsx import { render, screen } from '@testing-library/react'; import Home from '@/app/page'; describe('Home', () => { it('renders a heading', () => { render(); const heading = screen.getByRole('heading', { level: 1 }); expect(heading).toBeInTheDocument(); }); });
部署
生产配置
// next.config.js /** @type {import('next').NextConfig} */ const nextConfig = { images: { domains: ['tu-dominio.com'], }, async redirects() { return [ { source: '/old-page', destination: '/new-page', permanent: true, }, ]; }, }; module.exports = nextConfig;
实践能力卓越
app/ ├── (auth)/ │ ├── login/ │ └── register/ ├── (dashboard)/ │ ├── profile/ │ └── settings/ └── (marketing)/ ├── about/ └── contact/
// app/error.tsx 'use client'; export default function Error({ error, reset, }: { error: Error & { digest?: string }; reset: () => void; }) { return (); }¡Algo salió mal!
// app/loading.tsx export default function Loading() { return (); }
结论
Next.js 14 的摘要:
这是理想的选择: