框架的说明书是写给 AI 看的:我用 Next.js 搭了个博客
前几天跑 npx create-next-app@latest 新建了个项目,页面写得差不多了,准备提交。git diff 一打开,里面躺着一个我从没创建过的文件:AGENTS.md。
第一行是这么写的:
markdown
# This is NOT the Next.js you know
This version has breaking changes --- APIs, conventions, and file structure
may all differ from your training data. Read the relevant guide in
`node_modules/next/dist/docs/` ... before writing any code.
翻译过来大意是:这不是你训练数据里那个 Next.js,这个版本有破坏性变更,API、约定、文件结构都可能不一样,写代码之前先去读 node_modules 里的文档。
我愣了几秒。这不是我写的,是 next dev 跑起来的时候自动生成的。而且看内容,它根本不是写给人的------是写给 AI 看的。注释里还特意说明:这个块会被 next dev 反复写入,删掉它只会重新出现,跟着代码一起提交才能保持工作区干净。
框架主动给 AI 喂了一份说明书。这个发现让我重新想了一个问题:框架到底是给谁用的。
一、先回答:框架是什么
之前用 Next.js 做过官网和笔记系统,都是照着文档把功能堆出来,能跑就行,没认真想过"框架"这个词到底意味着什么。这次翻了些资料,发现一个比喻很贴切:
框架 = 建筑蓝图 + 工具箱。
它提供了一个包含地基、墙壁、屋顶的基本架构,你不需要从 0 开始盖房子,只需要关注组装和装修------也就是业务本身。不用框架,你面对的是一堆散乱的积木和工具;用了框架,你拿到的是一盒带说明书、待拼装的乐高。
有意思的地方在于:这份说明书以前只有开发者能读,现在 AI 也能读。
我还注意到一个更深的呼应。上次研究 SDD(规范驱动开发)的时候写过:先写规范、再让 AI 按规范实现,产出质量会高很多。框架提供的这套约束和最佳实践,本质上就是一份现成的规范文档------和 SDD 的思路不谋而合。等于说框架天然就是给"人 + AI"协作准备的那份上下文。
二、React 解决了一半问题
要理解 Next.js 的价值,得先看清 React 的定位。React 是一个库,不是框架。它做的事可以浓缩成一句:返回 JSX 的函数 + 响应式状态。
拿最经典的计数器举例,核心就一行:
JavaScript
const [count,setCount] = useState(0);
<>
{count}
onClick = {setCount(count++)}
<>
useState 给了你一个状态和它的更新函数,界面跟着状态自动变。这就把开发者从低级的前端 API 命令式流水线编程里解放出来了------不用手动 getElementById 再改 DOM,通过现代前端库(React/Vue 这类 MVVM 体系)直接写业务就好。
MVVM:Model-View-ViewModel,一种把视图和数据状态绑定起来的架构模式,视图随状态自动更新,不用手动操作 DOM。
但 React 只解决了"界面怎么渲染"这一半。另一半它不管:路由怎么组织?请求方法放哪?文件放哪?这些它都留给你自己决定。
对纯手写的人来说这是自由,对协作和 AI 生成来说这是灾难------每个人(每个模型)的答案都不一样,项目越长越乱。
关注业务,明白为什么需要组件,而不是纠结怎么写组件。这是 React 教我的事。而"文件放哪"这个问题,正是框架要接手的。
三、为什么 AI 越强,越要上框架
我原本的直觉是:AI 代码能力越强,框架越不重要------反正它什么都能写。实际了解下来发现反了。
先看传统的前后端全栈开发,通常是 React + Java/Python:
- 对开发者:多语言开发,学习周期长,成本高
- 对 AI:上下文切换成本高,脑子里得同时装两套语言的生态和约定
而 Next.js 给到 AI 的上下文是一整套:组件(描述组件)+ 响应式业务 + 服务器端渲染 + API。前后端同一种语言、同一套约定,AI 不用来回切换。
具体到"文件放哪"这个刚才的问题,框架直接给了标准答案:
- 图片放
/public/ - 页面放
/app/下,一个目录一个路由 - 组件放
/app/components(或独立的components目录)
准确说,App Router 的约定是 app 目录下每个文件夹对应一段 URL,文件夹里的 page.tsx 就是这个路由的页面。位置统一了,AI 生成的项目自然就规范化------不会这次图片扔根目录、下次塞进 src/assets。
再叠加几个选型理由:
Claude、Codex 的原生支持。 Next.js 约束优秀、代码简化(CSR、SSR 开箱即用),主流 AI 编码工具对它的理解最深。
生态够厚。 shadcn/ui 提供组件库(角色类似传统前端的 ElementUI、ANTD,但设计更现代,而且特别适合让 AI 按需引入和改写组件);tailwindcss 用原子类名写样式,类名自带语义(flex、gap-6、text-sm),AI 的语义理解能力正好吃得下这一套。
Vercel。 Next.js 背后的公司,全球唯一一家专注 JS 栈 AI Coding Agent 以及生态的技术公司。应用可以快捷发布上线,自动绑定二级域名,写完就能给别人看。
把这些拼起来,我才理解笔记里那句话的分量:借助 Next.js 框架提供的约束和规范,AI 辅助前端开发的工具/机制才能真正落地、发挥作用。 上次写 FDE 的时候提过"Harness(执行脚手架)落地"这个概念,当时还是抽象的。这次看到 AGENTS.md 的瞬间,它具象了:框架给 AI 一套约束、一套上下文,AI 才能更高效地按约束开发项目。next dev 自动写入 AGENTS.md,就是这个逻辑的产品级实现。
四、文件系统路由:约定即答案
真正动手搭博客,才知道"约定"二字有多省心。Next.js App Router 的路由全靠文件系统映射,核心就这么几条。
约定文件清单:
page.tsx------ 页面本体,目录的门面layout.tsx------ 共享的布局loading.tsx------ 加载页面not-found.tsx------ 404 页面error.tsx------ 错误 UI
目录名直接映射到 URL 路径。 app/about/page.tsx 就是 /about 页面,app/blog/page.tsx 就是 /blog页面。没有路由配置文件,目录即路由。
拿我项目里的 layout.tsx 举例,根布局长这样(节选):
tsx
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import Link from "next/link";
import "./globals.css";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({ children }: LayoutProps<"/">) {
return (
<html lang="en" className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}>
<body className="min-h-full flex flex-col">
<header className="sticky top-0 z-10 border-b ...">
<nav>
<Link href="/">Next.js</Link>
<Link href="/about">About</Link>
<Link href="/blog">Blog</Link>
</nav>
</header>
{children}
</body>
</html>
);
}
全站的 header 导航、字体、metadata(SEO 元信息)都收在这一层,所有页面共享,导航切换时它不重新渲染。注意 LayoutProps<"/"> 这个类型------我没定义过它,是 Next.js 自动生成的全局类型,路由路径直接进了类型系统。
博客列表页更直接,组件里直接调数据函数:
tsx
import { getAllPosts } from "@/lib/posts";
export default function Blog() {
const posts = getAllPosts();
return (
<div className="mt-12 grid gap-6 sm:grid-cols-2">
{posts.map((post) => (
<Link key={post.slug} href={`/blog/${post.slug}`}>
...
</Link>
))}
</div>
);
}
没有 useEffect、没有请求封装,getAllPosts() 直接返回数据。因为页面默认就是服务端组件,跑在服务端。
动态路由 是 [slug] 目录,方括号就是 URL 参数。这里第一次见到两个新约定,值得单独说:
tsx
type Props = PageProps<"/blog/[slug]">;
export function generateStaticParams() {
return getAllPosts().map((post) => ({ slug: post.slug }));
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { slug } = await params;
const post = getPostBySlug(slug);
if (!post) return {};
return {
title: post.title,
description: post.excerpt,
};
}
export default async function BlogPostPage({ params }: Props) {
const { slug } = await params;
const post = getPostBySlug(slug);
if (!post) notFound();
...
}
generateStaticParams:构建时(npm run build)把所有 slug 预先静态生成,不用等请求来了再渲染generateMetadata:每篇文章动态生成自己的标题和描述,SEO 逐页定制notFound():数据查不到就直接触发not-found.tsx渲染 404------上面那个 404 页面就是被它唤起的
回看这一节,我一行"路由配置"都没写。目录建好、文件命名对,路由、类型、静态生成、404 兜底全部就位。约定即答案,这四个字是 App Router 的全部。
五、Link 不是换皮的 a 标签
最后一个知识点,藏得最深:next/link 的 Link 组件和原生 <a> 的区别。
表面看都是跳转。区别在于 Link 走的是客户端导航------无需刷新页面,类似单页应用的局部更新。而这是需要请求后端的,只是不整页刷新(页面不会白一下)。
前端路由:Hash 路由和 History 路由,通过改 URL 局部刷新页面,解决了 SEO 问题,体验又类似 SPA。
具体机制:前端导航时,Next.js 会自动发一个 RSC Payload(React Server Component 序列化后的数据结构),只改需要改的地方。数据是从后端拿的,只是走 Ajax 请求,不是浏览器传统的整页导航。
RSC(React Server Component):在服务端运行的 React 组件,渲染结果序列化后发给客户端,客户端 JS 体积大幅减少。
还有个容易被忽略的细节:Link 会预加载可连接的页面 。加上 prefetch 属性后,浏览器空闲时就会提前下载目标页的数据,点过去就是"秒开"。原理和资源预加载同源,HTML 里早就有类似的东西:
HTML
<link rel="prefetch" href="/blog">
<link data-n-head="ssr" rel="dns-prefetch" href="//lf3-short.ibytedapm.com">
第二行的 dns-prefetch 值得展开一下,因为它牵出一个基础概念------DNS。
DNS 是域名系统------一张 key:value 的分布式数据库,通过域名去查询对应的实际 IP 地址。domain → ip 的查询要经过服务商的解析,是需要时间的。所以提前告诉浏览器"这个域名待会要用",真正发请求时 DNS 解析就已经就绪了。省的就是这点解析时间。
一个 Link,背后是前端路由 + RSC 序列化 + 数据预取 + DNS 预解析的组合拳。以前我用 <a> 标签跳页面从来不想这些,现在明白框架把多少事悄悄做掉了。
我现在的理解
以前我对框架的理解是"给开发者省事的工具"。现在我觉得框架更像一份双份说明书:一份给人看------约定什么文件放在什么位置;一份给 AI 看------AGENTS.md、类型系统、代码结构本身就是上下文。
AI 时代框架的价值不降反升:约束即上下文,上下文决定生成质量。 Vibe Coding 阶段 AI 拿到的是散乱积木,产出演示 Demo 尚可;框架阶段 AI 拿到的是带说明书的乐高,产出才是工程。这也解释了为什么 Claude 和 Codex 都对 Next.js 支持最深------不是偏爱,是这份说明书写得足够清楚。
搭完这个博客,路由、布局、动态参数、404 兜底我一行配置没写,全是约定给的。下一步想碰 loading.tsx 和流式渲染,把首屏体验那块也补上。
术语速查
- 框架(Framework):提供地基、墙壁、屋顶等基本架构的半成品房子,开发者只负责组装和装修(业务),不从 0 盖房。
- SSR / CSR:服务器端渲染(Server-Side Rendering,页面在服务端渲染成 HTML 再发送)与客户端渲染(Client-Side Rendering,浏览器下载 JS 后渲染)。Next.js 两者开箱即用。
- 静态生成 :构建时就预先生成好页面 HTML(如
generateStaticParams预生成所有 slug),请求来了直接返回,不占用运行时渲染。 - RSC Payload:React Server Component 序列化后的数据结构,前端导航时 Next.js 自动发送,只更新需要变化的部分。
- Hash / History 路由 :两种前端路由实现。Hash 路由靠 URL 的
#部分变化(不触发服务端请求);History 路由靠 History API 改路径。都能做到局部刷新。 - DNS / dns-prefetch :DNS 是域名系统,分布式 key:value 数据库,负责域名到 IP 的解析;
dns-prefetch提前完成解析,省去请求时的等待。 - shadcn/ui:现代 React 组件库,定位类似 ElementUI / ANTD,但以源码形式引入组件,适合 AI 按需改写。
- tailwindcss :原子化 CSS 方案,类名自带语义(如
flex、gap-6),与 AI 的语义理解能力天然契合。 - Vercel:Next.js 背后的公司,专注 JS 栈 AI Coding Agent 与生态,支持一键部署并自动绑定二级域名。
- AGENTS.md :写给 AI 编码工具的项目规则文件,
next dev会自动写入并维护。