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 的摘要:
这是理想的选择: