Next.js 教程(手把手讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言:为什么选择 Next.js?

在现代 Web 开发领域,Next.js 凭借其对 React 的增强功能和开箱即用的优化,成为全栈开发者的热门选择。它不仅简化了传统 React 应用的复杂配置,还提供了服务器端渲染(SSR)、静态生成(SSG)、API 路由等核心功能,帮助开发者高效构建高性能的网页应用。无论是构建个人博客、电商网站还是企业级应用,Next.js 都能提供灵活且高效的解决方案。

本教程面向编程初学者和中级开发者,通过循序渐进的方式,结合实际案例和代码示例,帮助读者掌握 Next.js 的核心概念与实践技巧。


一、环境搭建与项目初始化

1.1 安装 Node.js 和 npm

Next.js 需要 Node.js 18.0 或更高版本。首先,访问 Node.js 官网 下载并安装对应操作系统的版本。安装完成后,通过以下命令验证版本:

node -v  
npm -v  

1.2 创建 Next.js 项目

使用 create-next-app 脚手架快速初始化项目:

npx create-next-app@latest nextjs-tutorial  
cd nextjs-tutorial  

运行项目:

npm run dev  

访问 http://localhost:3000,即可看到默认的 Next.js 欢迎页面。

1.3 项目结构解析

一个典型的 Next.js 项目目录如下:

nextjs-tutorial/  
├── node_modules/  
├── public/         # 存放静态资源(如图片、字体)  
├── pages/          # 核心目录,定义路由和页面  
├── styles/         # 存放全局样式文件  
├── package.json    # 项目依赖和脚本配置  
└── README.md       # 文档说明  

关键概念比喻

  • pages/ 目录就像网站的“导航地图”,每个文件名对应一个路由路径。例如,pages/about.js 自动映射到 /about 路由。

二、核心功能详解:从基础到进阶

2.1 页面与路由

2.1.1 静态页面的创建

pages/ 目录下新建 blog.js 文件,编写如下代码:

// pages/blog.js  
export default function Blog() {  
  return (  
    <div>  
      <h1>欢迎访问我的博客</h1>  
      <p>这里会展示最新的文章列表...</p>  
    </div>  
  );  
}  

访问 http://localhost:3000/blog,即可看到该页面。

2.1.2 动态路由与嵌套路由

动态路由:通过 [][...slug] 定义动态路径段。例如:

pages/  
├── blog/          # 嵌套路由目录  
│   ├── [id].js    # 动态路径 /blog/123  
│   └── index.js   # 固定路径 /blog  
└── post/[slug].js # 动态路径 /post/next-js-tutorial  

[id].js 中,可以通过 useParams 钩子获取动态参数:

// pages/blog/[id].js  
import { useParams } from 'next/navigation';  

export default function BlogPost() {  
  const { id } = useParams();  
  return <h1>文章 ID: {id}</h1>;  
}  

2.2 数据获取策略

Next.js 提供了多种数据获取方法,适用于不同场景。

2.2.1 静态生成(Static Generation, SSG)

通过 getStaticProps 在构建时预渲染页面:

// pages/index.js  
export async function getStaticProps() {  
  const res = await fetch('https://api.example.com/posts');  
  const posts = await res.json();  
  return { props: { posts }, revalidate: 10 }; // 10秒后重新验证  
}  

export default function Home({ posts }) {  
  return (  
    <div>  
      {posts.map(post => (  
        <div key={post.id}>{post.title}</div>  
      ))}  
    </div>  
  );  
}  

比喻:SSG 就像预制菜工厂,提前准备好所有菜品(页面内容),用户访问时直接“开盒即食”,无需等待烹饪(数据请求)。

2.2.2 服务器端渲染(Server-Side Rendering, SSR)

通过 getServerSideProps 在每次请求时获取数据:

// pages/dashboard.js  
export async function getServerSideProps() {  
  const res = await fetch('https://api.example.com/realtime-data');  
  const data = await res.json();  
  return { props: { data } };  
}  

export default function Dashboard({ data }) {  
  return <div>实时数据:{data.value}</div>;  
}  

适用场景:需要实时数据(如用户登录状态、动态计数器)时使用。

2.2.3 客户端数据获取

直接在组件中使用 useEffectfetch

// pages/client-data.js  
import { useEffect, useState } from 'react';  

export default function ClientData() {  
  const [data, setData] = useState(null);  

  useEffect(() => {  
    fetch('https://api.example.com/client-endpoint')  
      .then(res => res.json())  
      .then(result => setData(result));  
  }, []);  

  return <div>客户端数据:{data?.value}</div>;  
}  

2.3 API 路由与后端集成

Next.js 允许在 pages/api/ 目录下创建 RESTful API:

pages/  
└── api/  
    └── posts.js  
// pages/api/posts.js  
export default function handler(req, res) {  
  const posts = [  
    { id: 1, title: 'Next.js 教程' },  
    // ...更多数据  
  ];  
  res.status(200).json(posts);  
}  

通过 fetch('/api/posts') 即可调用此 API,无需配置 CORS。


三、高级功能与最佳实践

3.1 图片优化与 Image 组件

Next.js 的 Image 组件结合自动优化、懒加载和自适应图片:

// pages/image-example.js  
import Image from 'next/image';  

export default function ImageExample() {  
  return (  
    <div>  
      <Image  
        src="/logo.png"  
        alt="Next.js Logo"  
        width={300}  
        height={100}  
        quality={75}  
        placeholder="blur"  
      />  
    </div>  
  );  
}  

3.2 国际化(i18n)支持

通过 next.config.js 配置多语言:

// next.config.js  
module.exports = {  
  i18n: {  
    locales: ['en', 'zh-CN'],  
    defaultLocale: 'en',  
  },  
};  

pages/ 目录下创建 locales 子目录:

pages/  
├── en/  
│   └── about.js  
└── zh-CN/  
    └── about.js  

3.3 性能优化与部署

3.3.1 缓存与预渲染

利用 revalidate 参数控制 SSG 页面的缓存更新:

export async function getStaticProps() {  
  // ...数据获取逻辑  
  return { props: { data }, revalidate: 60 }; // 60秒后重新生成  
}  

3.3.2 部署到 Vercel

Next.js 与 Vercel 完美集成,只需通过命令行一键部署:

npm install -g vercel  
vercel  

四、实际案例:构建一个博客应用

4.1 需求分析

目标:创建一个支持动态路由、SSG 生成和 API 调用的博客系统。

4.2 步骤分解

4.2.1 创建博客列表页面

pages/blog.js 中实现:

// pages/blog.js  
import Link from 'next/link';  

export async function getStaticProps() {  
  const res = await fetch('https://jsonplaceholder.typicode.com/posts');  
  const posts = await res.json();  
  return { props: { posts }, revalidate: 60 };  
}  

export default function Blog({ posts }) {  
  return (  
    <div>  
      {posts.slice(0, 5).map(post => (  
        <div key={post.id}>  
          <Link href={`/blog/${post.id}`}>  
            <a>{post.title}</a>  
          </Link>  
        </div>  
      ))}  
    </div>  
  );  
}  

4.2.2 实现动态文章页面

pages/blog/[id].js 中:

// pages/blog/[id].js  
import { useRouter } from 'next/router';  

export async function getStaticPaths() {  
  const res = await fetch('https://jsonplaceholder.typicode.com/posts');  
  const posts = await res.json();  
  const paths = posts.map(post => ({ params: { id: post.id.toString() } }));  
  return { paths, fallback: false };  
}  

export async function getStaticProps({ params }) {  
  const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);  
  const post = await res.json();  
  return { props: { post } };  
}  

export default function BlogPost({ post }) {  
  const router = useRouter();  
  if (router.isFallback) {  
    return <div>Loading...</div>;  
  }  
  return (  
    <div>  
      <h1>{post.title}</h1>  
      <p>{post.body}</p>  
    </div>  
  );  
}  

4.2.3 添加评论功能(通过 API 路由)

pages/api/comments.js 中:

// pages/api/comments.js  
import { PrismaClient } from '@prisma/client';  

const prisma = new PrismaClient();  

export default async function handler(req, res) {  
  if (req.method === 'POST') {  
    const { postId, author, content } = req.body;  
    const comment = await prisma.comment.create({  
      data: { postId, author, content },  
    });  
    return res.status(201).json(comment);  
  }  
}  

结论:Next.js 的未来与你

通过本教程,读者已掌握了从环境搭建到高级功能的 Next.js 核心知识。Next.js 不仅简化了复杂配置,还通过 SSG、SSR、API 路由等特性,让开发者能够高效构建高性能应用。无论是个人项目还是企业级需求,Next.js 都能提供灵活且强大的支持。

建议读者继续探索官方文档和社区资源,尝试将所学知识应用于实际项目中。随着实践的深入,Next.js 的潜力将被进一步激发,助你成为全栈开发领域的佼佼者。


关键词布局提示:本文围绕“Next.js 教程”展开,通过分步讲解、代码示例和实际案例,帮助读者系统掌握 Next.js 的核心功能与最佳实践。

最新发布