ホームページ >ウェブフロントエンド >jsチュートリアル >Next.js: 最も人気のある React フレームワークの決定版ガイド
Next.js は、最新の Web アプリケーションを構築するための最も人気のある React フレームワークになりました。 Next.js は、サーバーサイド レンダリング (SSR)、静的生成、優れた開発エクスペリエンスに重点を置いており、高性能でスケーラブルな Web アプリケーションを構築するために必要なものをすべて提供します。
ハイブリッド レンダリング
自動最適化
開発者エクスペリエンス
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 のオファー:
次のような場合に最適です。
プロジェクトで Next.js を使用していますか?どの機能が最も便利だと思いますか?コメントであなたの経験を共有してください! ?
以上がNext.js: 最も人気のある React フレームワークの決定版ガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。