Heim >Web-Frontend >js-Tutorial >Next.js: Der endgültige Leitfaden zum beliebtesten React Framework
Next.js hat sich zum beliebtesten React-Framework für die Erstellung moderner Webanwendungen entwickelt. Mit seinem Fokus auf serverseitigem Rendering (SSR), statischer Generierung und einer hervorragenden Entwicklungserfahrung bietet Next.js alles, was Sie zum Erstellen leistungsstarker, skalierbarer Webanwendungen benötigen.
Hybrid-Rendering
Automatische Optimierungen
Entwicklererfahrung
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
// app/page.tsx export default function Home() { return ( <main> <h1>Bienvenidos a Next.js</h1> </main> ); }
// app/blog/[slug]/page.tsx export default function BlogPost({ params }: { params: { slug: string } }) { return ( <article> <h1>Post: {params.slug}</h1> </article> ); }
// app/layout.tsx import { Inter } from 'next/font/google'; const inter = Inter({ subsets: ['latin'] }); export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body className={inter.className}> <nav> {/* Navegación común */} </nav> {children} </body> </html> ); }
// 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 ( <div> {posts.map(post => ( <article key={post.id}> <h2>{post.title}</h2> <p>{post.excerpt}</p> </article> ))} </div> ); }
// 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 ( <article> <h1>{post.title}</h1> <div>{post.content}</div> </article> ); }
// 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 ( <Image src="/perfil.jpg" alt="Foto de perfil" width={500} height={300} priority /> ); }
import { Roboto } from 'next/font/google'; const roboto = Roboto({ weight: ['400', '700'], subsets: ['latin'], display: 'swap', }); export default function Layout({ children }) { return ( <div className={roboto.className}> {children} </div> ); }
'use client'; import { useState } from 'react'; export default function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Contador: {count}</p> <button onClick={() => setCount(count + 1)}> Incrementar </button> </div> ); }
// components/Button.tsx import styles from './Button.module.css'; export default function Button({ children }) { return ( <button className={styles.button}> {children} </button> ); }
export default function Card({ title, content }) { return ( <div className="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4"> <div> <div className="text-xl font-medium text-black">{title}</div> <p className="text-gray-500">{content}</p> </div> </div> ); }
// 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(<Home />); 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 ( <div> <h2>¡Algo salió mal!</h2> <button onClick={() => reset()}>Intentar de nuevo</button> </div> ); }
// app/loading.tsx export default function Loading() { return ( <div className="flex items-center justify-center"> <div className="animate-spin rounded-full h-32 w-32 border-b-2 border-gray-900" /> </div> ); }
Next.js 14 bietet:
Es ist die ideale Wahl für:
Verwenden Sie Next.js in Ihren Projekten? Welche Funktionen finden Sie am nützlichsten? Teilen Sie Ihre Erfahrungen in den Kommentaren! ?
Das obige ist der detaillierte Inhalt vonNext.js: Der endgültige Leitfaden zum beliebtesten React Framework. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!