Next.js 是一个运行在 Node.js 服务器上的全栈框架,它用服务端能力来增强前端应用的性能和开发体验。它不是纯粹的前端或后端,而是以前端开发体验为中心,整合了后端能力的完整解决方案。
本文为Next.js学习指引,并非Next.js的教程本身。系统学习Next.js,请参看:
- Next.js 官方教程:https://nextjs.org/learn
- Next.js 视频教程: https://www.youtube.com/watch?v=b4ba60j_4o8&list=PLC3y8-rFHvwhIEc4I4YsRz5C7GOBnxSJY
判断自己学会的标准:本人能够看懂每一行由AI工具生成的代码。
序言:NodeJS、npm、Next.js 三者的关系 #
| 技术 | 说明 |
|---|---|
| NodeJS | 房屋地基和主体框架,提供坚实基础,保证项目可以运行起来 |
| NPM | 建筑的工具箱和建材商店,需要自己没有的建筑材料时,通过它来完成购入(安装)。避免所有的材料自己建造。 |
| Next.js | 房屋设计方案,帮我们规划了房间布置,方便我们清晰的知道什么设施(代码)放在什么位置,方便管理 |
首先安装NodeJS,其自带NPM。然后用NPM安装Next.js。这样就可以开始建造房屋(代码项目工程)了。
入门Next.js #
环境准备 #
- 打开终端,输入 npx create-next-app@latest ,点击回车
- 一直点击回车,选择默认选项即可
- 等待项目创建完成,Next.js初始项目文件就创建好了。要记住项目路径
- 打开Cursor,打开上面的项目路径即可
项目结构 #
Next.js 项目结构如下:
├── app/ # ➜*App Router 核心*
│ ├── layout.tsx # 所有子路由的根布局
│ ├── page.tsx # 访问 / 时渲染
│ └── globals.css
├── public/ # 静态资源
├── tsconfig.json
└── tailwind.config.ts
app文件夹 : Next.js路由核心。在这个文件夹下,每个文件或者文件夹都对应一个页面路由。例如,创建一个 home.js(或者 home.tsx)文件在app文件夹下,就可以通过浏览器访问对应的页面;如果创建子文件夹,如 app/blog/[slug].js , 可以实现动态路由,用于展示博客详情页。举个例子:
- 创建app/home.js 访问 http://localhost:3000 就可以看到这个页面
- 创建 app/blog/[id].js 访问 http://localhost:3000/blog/[id] 就可以根据id显示对应的文章
public文件夹: 用于存储静态资源,如图像、字体、图标等。在页面中使用相对路径应用这些资源,例如在组件中使用< img src="/logo.png" alt=“公司logo”,这里的logo就可以放在public文件夹下。
运行项目 #
启动开发环境 : 终端运行 npm run dev ,会在终端出现一个访问地址,在浏览器中打开地址,就可以看到相应页面了。举个例子:
- 在app文件夹下建一个 about文件夹,在about文件夹内创建一个 page.tsx
- 在 http://localhost:3000/about ,查看页面
Next.js 会自动将app文件夹下的文件和文件夹结构映射为对应的URL路径
- 文件夹对应的URL路径中的路径段。创建about 文件夹,就对应了URL中的/about 路径部分
- page 文件是可公开访问的页面组件载体。当在 about文件夹中创建page文件时,它所导出的React组件内容,会被渲染到该文件夹对应的URL路径页面上。比如 about/page.tsx 中导出的组件,会在访问/about 时展示给用户。page文件就像一个页面内容提供者,告诉浏览器在对应的URL下显示什么。
注意:一个文件夹about下,仅page.tsx会被渲染加载,可以通过 http://localhost:3000/about 访问。 其他tsx文件并不能加载显示。
组件 #
Next.js 里有两种组件(Components),分别是服务端组件和客户端组件。Next.js默认 Server Components,仅在需要浏览器交互时才标注 “use client”。
服务端组件(Server Components)
运行在 Node 边缘 / Serverless。可直接调用后端 SDK、数据库、文件系统。生成纯 HTML,体积小,SEO 友好。
import { fetchUsers } from "@/lib/api";
export default async function Users() {
const users = await fetchUsers(); // 直接 await
return (
<ul>
{users.map(u => <li key={u.id}>{u.name}</li>)}
</ul>
);
}
客户端组件 (Client Components)
"use client";
import { useState } from "react";
export default function Counter() {
const [n, setN] = useState(0);
return (
<button
className="rounded bg-blue-600 px-3 py-1 text-white"
onClick={() => setN(n + 1)}
>
点击 {n}
</button>
);
}
共享布局 layout.tsx
export const metadata = { title: "一小时 Next.js" };
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="zh">
<body className="prose mx-auto p-4">{children}</body>
</html>
);
}
数据获取 #
如果在Server Component里,可以直接使用fetch()函数获取数据、以及调用API。
export default async function ApiExample() {
const res = await fetch("https://jsonplaceholder.typicode.com/users", {
// 缓存 60 秒,等同 ISR
next: { revalidate: 60 }
});
const users: { id: number; name: string }[] = await res.json();
return (
<ul className="list-disc pl-5">
{users.map(u => (
<li key={u.id}>{u.name}</li>
))}
</ul>
);
}
如果时在 client Component 里,可以使用Ajax的方式获取数据。
"use client";
import { useEffect, useState } from "react";
type User = { id: number; name: string };
export default function UsersClient() {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then(r => {
if (!r.ok) throw new Error("请求失败");
return r.json();
})
.then((data: User[]) => setUsers(data))
.catch(err => setError(err))
.finally(() => setLoading(false));
}, []); // 只在首屏执行一次
if (loading) return <p>加载中…</p>;
if (error) return <p className="text-red-600">出错:{error.message}</p>;
return (
<ul className="list-disc pl-5">
{users.map(u => (
<li key={u.id}>{u.name}</li>
))}
</ul>
);
}
相关说明:
- “use client” : 声明这是 Client Component
- 用 useEffect 把网络请求放到浏览器执行,避免 SSR 时跑两遍。
- 本地维护 loading / error / data 三态即可;初学者先别上管理库。
- 与 Server 组件不同,这里无法使用 revalidate 等 Next.js 缓存指令,完全由浏览器缓存策略决定。
元数据 & SEO #
元数据就是"关于网页的介绍信息"。当你把网页链接分享到微信、Twitter 时,会显示一个卡片,上面有标题、描述、配图——这些就是元数据在起作用。 同时,搜索引擎(百度、Google)也靠读取这些信息来理解你的网页内容,从而决定在搜索结果中如何展示你的页面。
export const revalidate = 60; // ISR - 每60秒重新生成一次
export async function generateMetadata({ params }) {
const post = await fetchPost(params.slug); // 获取文章数据
return {
title: post.title, // 网页标题(浏览器标签页显示)
description: post.excerpt, // 网页描述(搜索结果下方的简介)
openGraph: { // 社交媒体分享卡片
images: post.cover // 分享时显示的配图
}
};
}
title - 页面标题 :
title: post.title // 比如 "10分钟学会 React Hooks"
显示在浏览器标题页,显示在搜索结果的额蓝色标题位置,SEO最重要的一环,需要包含关键词。
description - 页面描述 :
description: post.excerpt // 比如 "本文用最简单的例子教你..."
显示在搜索结果标题下方的灰色文字,让用户快速了解页面内容,提高点击率。
opengraph - 社交分享卡片 :
openGraph: {
images: post.cover // 分享链接时显示的大图
}
在微信/X/Facebook分享时,会显示漂亮的卡片。有图有真相,分享效率翻倍。
如果没有设置数据,搜索结果就会显示一串网址,很丑。
#Next.js #AI出海指南最后一次修改于 2025-12-12