本章定位
上一章,我们已经正式开启了第五阶段综合实战。
你已经先把这次个人博客项目最关键的前置问题想清楚了:
- 这个项目为什么值得做。
- 这个项目主要做给谁看。
- 第一版必须完成哪些核心页面。
- 第一版先不做什么。
- 为什么框架继续选 Next.js,语言继续选 TypeScript。
- 为什么第一版先用本地 TypeScript 数据文件和 CSS Modules。
也就是说,到现在为止,你已经不是“模模糊糊想做个博客”,而是已经知道:
这个博客项目第一版的大致目标、边界、数据方向和技术路线是什么。
接下来,就到了非常关键的一步:
把这些想清楚的内容,真正落到项目骨架里。
这一章非常重要。
因为一个综合项目后面能不能写得稳,往往先取决于三件事:
- 项目是不是初始化得清楚。
- 路由目录是不是搭得清楚。
- 公共布局是不是一开始就组织得清楚。
如果这三件事一开始没理顺,后面页面越写越多,就很容易出现:
- 路由目录越来越乱
- 公共结构到处重复
- 页面和组件职责混在一起
- 样式和布局反复返工
所以这一篇我们不会急着把文章列表和详情逻辑全部写满。
这一篇的重点是:
- 先把项目创建出来。
- 先把
app/路由骨架搭出来。 - 先把公共导航、页脚和
layout.tsx组织起来。
你可以把这一章理解成:
第五阶段综合实战真正开始落地的第一篇,先把整个博客网站的地基搭稳。
本章学习目标
学完这一章后,你应该能做到:
- 理解为什么综合项目一开始,先搭骨架比先写很多细节页更稳。
- 学会用
pnpm create next-app创建一个适合当前阶段的 Next.js 项目。 - 知道初始化项目时哪些选项更适合当前这次博客实战。
- 理解
src/app、public、components、data、types等目录的基础职责。 - 学会按第一版页面清单搭出博客项目的路由结构。
- 理解
page.tsx、layout.tsx和动态路由目录的基础作用。 - 知道为什么博客项目需要先抽出公共导航和公共页脚。
- 学会用
layout.tsx把站点公共外壳连接起来。 - 理解
children在布局里的意义。 - 知道第一版项目初始化时,哪些内容先做占位,哪些细节后面再补。
- 掌握一个适合初学者继续扩展的博客项目目录骨架。
- 为下一篇继续进入首页、文章列表与本地数据接入做好准备。
一、这一篇到底要完成什么
这一篇我们要做的,不是马上把整个博客做完。
这一篇要完成的是:
先让博客网站“站起来”。
所谓“站起来”,主要是指下面这些事情:
- 项目已经创建完成,可以正常运行。
- 站点最基础的页面路由已经搭出来。
- 公共导航和页脚已经有了统一入口。
layout.tsx已经把整站公共骨架接起来。- 首页、文章列表页、文章详情页、关于页、联系页都已经有基础位置。
这一步非常关键。
因为从综合项目的角度看,它解决的是:
先让“网站结构”成立,而不是先让某个页面局部非常丰富。
二、为什么先搭项目骨架,比先写内容细节更重要
很多人在综合实战刚开始时,最容易做的事是:
先去写一个看起来最有意思的页面。
比如:
- 先写文章卡片
- 先写详情页排版
- 先写首页横幅区
这些当然都重要。
但如果路由和布局还没搭好,后面往往会遇到这些问题:
- 页面文件放哪儿开始犹豫。
- 导航要不要重写一遍。
- 页脚怎么每页都出现。
- 页面结构和样式会不会后面推翻重来。
所以更稳的节奏通常是:
先把站点骨架、公共外壳和页面入口搭起来,再往里填具体内容。
你可以把这一步理解成:
先把房子的承重墙和楼梯搭好,再去布置每个房间。
三、第一步:先创建项目
这一版博客项目,我们继续使用:
- Next.js
- TypeScript
src/目录- App Router
- CSS Modules + 全局样式
如果你使用pnpm,一个很适合当前阶段的初始化命令可以这样写:
pnpmcreate next-app personal-blog\--ts\--eslint\--app\--src-dir\--use-pnpm\--import-alias"@/*"1. 如果你是交互式创建,关键选项怎么选
如果创建过程中出现交互式问题,当前阶段建议这样选:
- TypeScript:
Yes - ESLint:
Yes - Tailwind CSS:
No src/directory:Yes- App Router:
Yes - Import alias:保持默认
@/*
2. 为什么这里先不选 Tailwind
不是因为 Tailwind 不好,而是因为这一套学习路线前面已经明确了:
第一版更适合继续用你已经掌握的 CSS 基础和 CSS Modules。
这样更有助于你真正建立:
- 布局组织感
- 样式分层感
- 组件局部样式边界感
3. 为什么src/目录值得打开
因为当前阶段项目文件会越来越多。
把源码统一放进src/,会更容易区分:
- 源码目录
- 配置文件
- 静态资源
四、项目创建完成后,先认识这些文件
项目创建出来后,不要急着立刻删改很多文件。
先认识当前最重要的几个入口。
如果我们使用了src/目录,第一版你通常会先看到这些东西:
personal-blog/ ├── public/ ├── src/ │ └── app/ │ ├── favicon.ico │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── package.json ├── tsconfig.json └── next.config.ts1.src/app/layout.tsx是什么
它是整站最基础的公共布局入口。
后面我们的:
- 页头
- 页脚
- 全局结构
都会慢慢接到这里。
2.src/app/page.tsx是什么
它对应网站首页,也就是:
/3.src/app/globals.css是什么
它负责全局基础样式,例如:
- 字体
- 背景
- 链接默认样式
- 通用容器规则
4.public/是什么
它适合放:
- 站点图片
- 图标
- 文章封面图
也就是那些:
会被页面直接引用的静态资源。
五、第二步:先把第一版路由目录搭出来
上一章我们已经明确了第一版最重要的五个页面:
- 首页
- 文章列表页
- 文章详情页
- 关于页
- 联系页
所以这一章最关键的动作之一,就是把这些页面先变成真实的目录结构。
一个适合第一版的src/app路由骨架可以先这样搭:
src/app/ ├── layout.tsx ├── page.tsx ├── posts/ │ ├── page.tsx │ └── [slug]/ │ └── page.tsx ├── about/ │ └── page.tsx └── contact/ └── page.tsx1. 这几个目录分别对应什么地址
你可以先建立下面这组直觉:
src/app/page.tsx对应/src/app/posts/page.tsx对应/postssrc/app/posts/[slug]/page.tsx对应/posts/某篇文章标识src/app/about/page.tsx对应/aboutsrc/app/contact/page.tsx对应/contact
2. 为什么先把目录搭出来很重要
因为它会帮你立刻把这些问题变清楚:
- 网站到底有哪些页面
- 页面之间的跳转路径是什么
- 哪些页面是静态入口,哪些页面是详情页入口
六、为什么文章详情页要用[slug]
博客项目里的文章详情页,不会只有一篇文章。
它通常是:
多篇文章共用同一个详情页结构,只是内容不同。
这时就很适合使用动态路由目录:
[slug]1.slug可以先怎么理解
你可以先把它理解成:
一篇文章在 URL 里的唯一标识。
例如:
react-basicnextjs-routingtypescript-generics
它们分别可以对应这样的网址:
/posts/react-basic /posts/nextjs-routing /posts/typescript-generics2. 为什么博客项目特别适合用这种方式
因为它天然符合:
同一类内容很多条,每条都有自己的详情页。
所以这一章虽然还不会把详情页数据全部写满,但我们要先把这条路由骨架搭出来。
七、先让每个页面“占住位置”
综合项目刚开始时,一个非常稳的做法是:
先让每个页面都有一个基础占位版本。
也就是说,先让这些页面都能打开,再逐步往里面填内容。
例如首页可以先写成:
export default function HomePage() { return ( <section> <h1>你好,这里是我的个人博客</h1> <p>后面我们会在这里接入个人介绍、推荐文章和内容入口。</p> </section> ); }文章列表页也可以先写成:
export default function PostsPage() { return ( <section> <h1>文章列表页</h1> <p>后面我们会在这里渲染文章卡片列表。</p> </section> ); }1. 为什么占位页很有价值
因为它可以帮助你先确认:
- 路由是否正确
- 页面是否能访问
- 公共布局是否已经套上
2. 当前阶段不需要一开始就让每页都很丰富
现在更重要的是:
每个页面的位置和职责先清楚地站住。
八、第三步:先准备导航配置
博客项目只要有多个页面,就会很快遇到一个问题:
导航到底怎么组织?
当前阶段更稳的做法通常是:
先把导航做成一份单独配置。
例如可以在src/data/site-nav.ts里先放这样一份数据:
exportinterfaceNavItem{label:string;href:string;}exportconstsiteNavList:NavItem[]=[{label:"首页",href:"/"},{label:"文章",href:"/posts"},{label:"关于",href:"/about"},{label:"联系",href:"/contact"}];1. 为什么导航值得先单独抽出来
因为它会被:
- 页头导航
- 可能的移动端菜单
- 后续的页脚快捷链接
重复使用。
2. 当前阶段最值得先建立什么意识
你可以先记住:
站点级配置,尽量不要直接写死在页面 JSX 里。
九、第四步:抽出SiteHeader
博客项目里,最值得先抽出来的公共组件之一,就是页头导航。
例如我们可以先在:
src/components/site-header.tsx创建一个基础组件。
它可以先写成这样:
import Link from "next/link"; import { siteNavList } from "@/data/site-nav"; export function SiteHeader() { return ( <header className="site-header"> <div className="site-shell"> <Link href="/" className="site-logo"> 从零开始学前端 </Link> <nav className="site-nav"> {siteNavList.map(function (navItem) { return ( <Link key={navItem.href} href={navItem.href}> {navItem.label} </Link> ); })} </nav> </div> </header> ); }1. 这段代码最关键的点是什么
不是样式,而是结构:
- Logo 区域有了
- 导航区域有了
- 导航来自统一配置
2. 为什么Link很重要
因为在 Next.js 项目里,页面之间跳转通常要优先使用:
Link它比直接写普通超链接更符合框架主线。
十、第五步:抽出SiteFooter
页脚和页头一样,也是很典型的公共结构。
第一版页脚不需要很复杂。
只要先把这些信息放上去,就已经非常有价值:
- 网站名称
- 一句简短说明
- 版权或年份信息
例如:
export function SiteFooter() { return ( <footer className="site-footer"> <div className="site-shell"> <p>从零开始学前端 | 个人博客项目</p> <p>这里会持续记录前端学习、项目实践与思考。</p> </div> </footer> ); }1. 为什么第一版页脚不需要做得太满
因为它当前最主要的价值是:
先让站点“有一个稳定结尾”。
2. 后面它还能继续扩展什么
后面完全可以再加:
- 社交链接
- 邮箱
- 快捷导航
- 更新时间说明
但现在先让骨架成立更重要。
十一、第六步:用layout.tsx把站点外壳接起来
这一步是本章最关键的核心动作之一。
因为layout.tsx会真正把:
- 页头
- 页面主体
- 页脚
连接成一个完整站点外壳。
一个适合当前阶段的src/app/layout.tsx可以先写成这样:
import type { Metadata } from "next"; import { SiteFooter } from "@/components/site-footer"; import { SiteHeader } from "@/components/site-header"; import "./globals.css"; export const metadata: Metadata = { title: "从零开始学前端 | 个人博客", description: "一个使用 Next.js 构建的个人博客项目" }; export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { return ( <html lang="zh-CN"> <body> <SiteHeader /> <main className="site-main"> {/* children 会被当前路由页面的内容替换 */} {children} </main> <SiteFooter /> </body> </html> ); }1. 这段代码里最值得先看懂什么
先看懂这四个点就够了:
- 全局样式从这里引入
- 页头和页脚从这里统一挂上
main区域是页面主体children是每个页面真正会变化的部分
2. 为什么这一步这么关键
因为从这一刻开始:
你的博客项目不再是一堆分散页面,而是已经有了统一站点外壳。
十二、为什么children是布局的主线
这一节很重要。
很多初学者第一次看layout.tsx时,最容易模糊的地方就是:
children到底是什么?
你现在可以先用最朴素的方式理解:
children就是当前路由页面会填进来的那块主要内容。
例如:
- 当你访问
/时,children会被首页内容替换。 - 当你访问
/posts时,children会被文章列表页内容替换。 - 当你访问
/about时,children会被关于页内容替换。
1. 为什么这能减少重复代码
因为页头和页脚不需要每个页面都重新写。
只要布局统一挂一次,页面就只关心自己的主体内容。
2. 这和前面学过的什么思想是一致的
它和我们前面反复强调的:
公共结构放公共层,变化内容放变化层
其实是同一条主线。
十三、第七步:先给页面一个统一容器层
当站点布局开始成形后,下一步很值得先做的,就是给页面准备一个统一容器。
因为博客项目里的很多页面,都会需要:
- 一定的最大宽度
- 左右留白
- 统一的内容区域节奏
当前阶段最简单的做法,是先在全局样式里约定一个通用类名,例如:
.site-shell{width:min(1100px,calc(100% - 32px));margin:0 auto;}1. 为什么这个容器层很重要
因为它可以帮助你让:
- 页头
- 页脚
- 页面内容
在视觉上保持统一宽度感。
2. 当前阶段最重要的不是样式多复杂
而是:
站点整体节奏开始统一。
十四、全局样式第一版先管什么
这一章我们不追求把所有视觉细节都定死。
但全局样式里,第一版至少可以先管下面几件事:
body的默认背景、文字颜色和字体- 链接默认样式
- 站点最大宽度容器
- 页头、页脚基础留白
main主区域的上下间距
例如:
:root{color-scheme:light;}*{box-sizing:border-box;}body{margin:0;color:#1f2937;background:#f8fafc;font-family:Arial,sans-serif;}a{color:inherit;text-decoration:none;}.site-main{padding:32px 0 56px;}1. 为什么这些基础样式就够重要
因为它们会直接影响:
- 站点是不是一打开就比较整齐
- 各页面是不是共享同一种基础节奏
2. 当前阶段不要先陷入什么
不要先陷入:
- 太细的动画效果
- 很复杂的主题系统
- 一次性铺满所有设计规范
现在更重要的是:
让站点骨架先稳定。
十五、第一版页面占位内容应该先写什么
有了路由和布局以后,下一步就可以让每个页面先写上最基础的占位内容。
但这个“占位”不是随便打一行字。
更稳的做法是:
让占位内容就开始体现页面职责。
例如:
1. 首页先写什么
可以先写:
- 网站主标题
- 一句站点说明
- 后面会接最近文章入口的提示
2. 文章列表页先写什么
可以先写:
- 列表页标题
- 一句说明
- 后面会接文章卡片列表的提示
3. 文章详情页先写什么
可以先写:
- 详情页标题占位
- 当前路由会展示具体文章内容的说明
4. 关于页先写什么
可以先写:
- 关于我标题
- 一段基础介绍占位
5. 联系页先写什么
可以先写:
- 联系我标题
- 后面会接联系表单的说明
6. 为什么这种占位方式更好
因为它已经开始让每个页面的职责清晰起来了。
后面你再往里填真实内容时,会自然很多。
十六、这一阶段先不急着做哪些细节
虽然这一章已经开始搭站点骨架,但有些细节现在还不需要急着做。
例如:
- 导航高亮
- 文章卡片完整样式
- 详情页正文排版细节
- 联系表单提交逻辑
- 图片优化细节
1. 为什么现在先不急
因为这一章的目标是:
先让路由、布局和公共结构跑起来。
如果这些地基还没稳,就急着做太多页面细节,后面很容易反复改动。
2. 当前阶段最稳的节奏是什么
先搭站点骨架,再逐步把:
- 首页内容
- 文章列表
- 文章详情
- 联系交互
一段一段接上去。
十七、第一版目录结构现在可以长什么样
结合这一章的初始化和公共布局内容,一个比较适合当前阶段的目录结构,现在可以先长成这样:
src/ ├── app/ │ ├── layout.tsx │ ├── page.tsx │ ├── posts/ │ │ ├── page.tsx │ │ └── [slug]/ │ │ └── page.tsx │ ├── about/ │ │ └── page.tsx │ ├── contact/ │ │ └── page.tsx │ └── globals.css ├── components/ │ ├── site-header.tsx │ └── site-footer.tsx ├── data/ │ └── site-nav.ts ├── lib/ ├── types/ └── styles/1. 为什么这个结构已经很有价值
因为它已经开始让几类职责分开了:
- 页面入口在
app/ - 公共结构在
components/ - 站点配置在
data/ - 工具函数和类型目录已经预留出来
2. 当前阶段不需要把所有目录一次填满
目录先留出来,不代表现在每个目录都必须有很多文件。
更重要的是:
你已经先把项目往清楚的方向搭起来了。
十八、开发过程中怎么验证这一步有没有搭好
这一章的成果,其实很适合通过最基础的方式快速验证。
你可以在项目启动后,逐个检查这些地址:
//posts/about/contact
如果这些页面都能打开,并且都共用了同一个页头和页脚,那就说明:
路由骨架和公共布局已经搭成功了。
1. 当前阶段验证的重点是什么
不是页面多漂亮,而是:
- 地址能否对应正确页面
- 布局是否统一生效
- 页面主体内容是否能被
children正常替换
2. 为什么这种“小验证”很重要
因为综合项目最怕的是一路猛写,到后面才发现骨架一开始就有问题。
现在这样小步确认,会稳很多。
十九、这一章最容易踩的几个坑
这一节建议你认真看。
因为博客项目刚起步时,很多问题看起来不大,但后面会反复拖慢你。
1. 坑一:项目初始化选项和技术路线不一致
例如上一章明明决定先用 CSS Modules,却创建时又把样式方案弄成完全另一套。
这会让后面学习主线变乱。
2. 坑二:路由目录一开始就随手乱放
这样后面一多页面,就很容易:
- 不知道文件放哪儿
- 静态页和详情页混在一起
3. 坑三:页头和页脚直接复制到每个页面
这样短期看方便,长期会非常难改。
4. 坑四:layout.tsx里塞太多页面专属逻辑
布局层更适合放公共结构,不适合一开始就混入大量页面独有内容。
5. 坑五:路由骨架没搭稳,就急着做复杂样式和交互
这样后面返工的概率会很高。
二十、本章实践练习
这一章的练习重点,是把“博客项目第一版骨架”真正搭起来。
1. 练习 1:创建项目并跑起来
请你用pnpm create next-app创建一个新的博客项目,并确认:
- TypeScript 已开启
- App Router 已开启
- 使用了
src/目录 - 项目可以通过
pnpm dev正常运行
这个练习的重点是:
把技术选型真正落到一个可运行项目里。
2. 练习 2:搭出第一版路由目录
请你根据这一章内容创建:
- 首页
- 文章列表页
- 文章详情页动态路由
- 关于页
- 联系页
这个练习会帮助你真正建立:
页面清单要变成真实目录结构,项目主线才算开始成立。
3. 练习 3:抽出SiteHeader和SiteFooter
请你把公共导航和页脚分别抽成组件,并通过layout.tsx统一挂载。
这个练习会帮助你真正理解:
公共结构应该放公共层,而不是写在每个页面里。
4. 练习 4:给所有页面先写职责占位
请你让首页、列表页、详情页、关于页、联系页都先有一份最小占位内容。
这个练习的重点是:
先让每个页面的职责站住,再逐步填充真实内容。
二十一、学习重点提示
这一章请你重点记住下面这些话:
- 综合项目开始落地时,最重要的不是马上写很多内容,而是先把项目骨架搭稳。
- 项目初始化、路由目录和公共布局,是博客项目后面能不能写得顺的基础。
- 第一版先把页面入口搭出来,比一开始就死磕页面细节更稳。
layout.tsx的核心价值,是把公共结构统一挂起来,让页面只关心自己的主体内容。children表示当前路由页面会被填进布局里的那块变化区域。- 导航配置、页头组件、页脚组件尽早抽出来,后面会省很多重复劳动。
- 骨架阶段先做占位页,是一种非常有效的小步推进方式。
- 先主结构,再主内容,再补交互和样式细节。
如果你只记一句话,请记住:
第五阶段综合实战真正开始落地时,最关键的不是谁先写出最花的页面,而是谁先把项目初始化、路由骨架和公共布局搭清楚。
二十二、本章小结
这一章,我们正式把第五阶段综合实战从“需求分析与技术选型”推进到了“项目骨架真正落地”的阶段。
你已经理解了:
- 为什么博客项目一开始要先搭骨架
- 项目初始化时哪些选项更适合当前这次实战
- 第一版页面清单应该怎样落成真实路由目录
- 为什么文章详情页适合使用
[slug]动态路由 - 为什么页头和页脚应该尽早抽成公共组件
layout.tsx和children在站点骨架里分别扮演什么角色- 全局样式第一版最值得先管哪些基础内容
- 为什么这一阶段先做占位页是一个更稳的推进方式
更重要的是,你开始真正建立一种非常关键的项目意识:
综合项目不是从某个漂亮模块开始,而是从项目地基开始。
这一步非常关键。
因为从这里开始,你已经不只是在学 Next.js 的概念,而是在开始真正进入:
个人博客项目第一版骨架的搭建阶段。
二十三、课后思考题
请你认真思考下面这些问题:
- 为什么综合项目一开始,先搭路由和布局会比先写某个局部页面更稳?
- 为什么第一版博客项目适合先让每个页面“占住位置”?
- 为什么页头和页脚尽早抽成公共组件会更省事?
layout.tsx和children的关系,最朴素的理解是什么?- 为什么动态路由
[slug]特别适合文章详情页? - 为什么项目初始化阶段不适合一开始就做太多页面样式和交互细节?
- 你觉得当前这套博客项目骨架里,哪一部分最容易在刚开始时被忽略?为什么?
建议你把这些问题用自己的话写下来。
只要你能把这些问题讲清楚,说明你已经真正开始进入第五阶段综合实战的落地主线了。
二十四、下一篇预告
下一篇我们会继续推进第五阶段综合实战,进入:
第五阶段综合实战:博客首页、文章列表与本地文章数据接入
到那时,你会开始真正把这一篇搭好的路由和布局骨架填起来:
- 本地文章数据怎么组织
- 首页怎么展示推荐内容
- 文章列表页怎么渲染文章卡片
- 内容页主线怎么真正开始跑起来
也就是说,下一篇开始,我们会从“项目初始化、路由设计与公共布局搭建”继续走到:
个人博客项目第一版内容展示主线的真正实现。