Next.js:React 流行框架的 La Guía Definitiva

Next.js 可以转换成流行的 React 框架,用于构建现代 Web 应用程序。结合 Lado del Servidor (SSR) 渲染、生成和开发体验,Next.js 需要构建 Web 应用程序可扩展和高级版本。

什么是 Next.js?

主要特征

  • 混合渲染 服务器端渲染 (SSR) 静态站点生成 (SSG) 客户端渲染 (CSR) 增量静态再生 (ISR)
  • 自动优化 图像优化 字体优化 脚本优化 零配置
  • 开发人员体验快速刷新 TypeScript 支持文件系统路由 API 路由
  • 普里梅罗斯帕索斯

    创建项目

    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 (
        

    Post: {params.slug}

    ); }

    共享布局

    // 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 (
        Foto de perfil
      );
    }

    字体

    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 的摘要:

  • 卓越的呈现
  • Excelente DX (开发者体验)
  • 可升级性
  • 渲染的灵活性
  • React 的完美集成
  • 这是理想的选择:

  • 网络应用程序
  • 电子商务网站
  • SaaS 应用程序
  • 动态内容站点
  • 附加资源

  • 官方文档
  • Next.js 示例
  • 学习 Next.js