框架的说明书是写给 AI 看的:我用 Next.js 搭了个博客

框架的说明书是写给 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 用原子类名写样式,类名自带语义(flexgap-6text-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 的路由全靠文件系统映射,核心就这么几条。

约定文件清单

  1. page.tsx ------ 页面本体,目录的门面
  2. layout.tsx ------ 共享的布局
  3. loading.tsx ------ 加载页面
  4. not-found.tsx ------ 404 页面
  5. 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 的全部。

最后一个知识点,藏得最深:next/linkLink 组件和原生 <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 方案,类名自带语义(如 flexgap-6),与 AI 的语义理解能力天然契合。
  • Vercel:Next.js 背后的公司,专注 JS 栈 AI Coding Agent 与生态,支持一键部署并自动绑定二级域名。
  • AGENTS.md :写给 AI 编码工具的项目规则文件,next dev 会自动写入并维护。
相关推荐
ZGIAI14 分钟前
ZGI 知识检索:让业务回答有据可查
人工智能·架构
2601_9556624628 分钟前
AI 配音工具 7 款实测:短视频、影视解说、小说推文音质横向对比
人工智能·音视频·语音识别·视频
AI创界者38 分钟前
PinkCherry-MiniMax-H3 全能AI视频整合包:8G显存开箱即用,支持首尾帧/超分补帧/自动提示词
人工智能·aigc
罗西的思考44 分钟前
【Agentic RL / 强化学习框架】Molt 设计解读
人工智能·算法·机器学习
Mr数据杨1 小时前
GNSS伪距误差预测实战案例 从Kaggle回归任务到城市定位误差补偿
人工智能·数据分析·kaggle竞赛
冬奇Lab1 小时前
Code Agent 解剖(15):Harness 设计之五——可观测性
人工智能·开源
冬奇Lab1 小时前
开源项目第203期:Cumora — AI Agent 与人类同队的跨平台团队协作工具
人工智能·开源·资讯
天远Date Lab1 小时前
零信任架构实战:基于天远双人婚姻评估查询构建自动化房产按揭联合审查网关
运维·人工智能·架构·自动化
甲维斯1 小时前
Claude Opus5 开发中转应用平台的5万字项目文档!
人工智能