从零开始学前端 | 第四十五章:第五阶段综合实战:个人博客项目初始化、路由设计与公共布局搭建
2026/7/23 14:56:22 网站建设 项目流程

本章定位

上一章,我们已经正式开启了第五阶段综合实战。

你已经先把这次个人博客项目最关键的前置问题想清楚了:

  1. 这个项目为什么值得做。
  2. 这个项目主要做给谁看。
  3. 第一版必须完成哪些核心页面。
  4. 第一版先不做什么。
  5. 为什么框架继续选 Next.js,语言继续选 TypeScript。
  6. 为什么第一版先用本地 TypeScript 数据文件和 CSS Modules。

也就是说,到现在为止,你已经不是“模模糊糊想做个博客”,而是已经知道:

这个博客项目第一版的大致目标、边界、数据方向和技术路线是什么。

接下来,就到了非常关键的一步:

把这些想清楚的内容,真正落到项目骨架里。

这一章非常重要。

因为一个综合项目后面能不能写得稳,往往先取决于三件事:

  1. 项目是不是初始化得清楚。
  2. 路由目录是不是搭得清楚。
  3. 公共布局是不是一开始就组织得清楚。

如果这三件事一开始没理顺,后面页面越写越多,就很容易出现:

  • 路由目录越来越乱
  • 公共结构到处重复
  • 页面和组件职责混在一起
  • 样式和布局反复返工

所以这一篇我们不会急着把文章列表和详情逻辑全部写满。

这一篇的重点是:

  1. 先把项目创建出来。
  2. 先把app/路由骨架搭出来。
  3. 先把公共导航、页脚和layout.tsx组织起来。

你可以把这一章理解成:

第五阶段综合实战真正开始落地的第一篇,先把整个博客网站的地基搭稳。

本章学习目标

学完这一章后,你应该能做到:

  1. 理解为什么综合项目一开始,先搭骨架比先写很多细节页更稳。
  2. 学会用pnpm create next-app创建一个适合当前阶段的 Next.js 项目。
  3. 知道初始化项目时哪些选项更适合当前这次博客实战。
  4. 理解src/apppubliccomponentsdatatypes等目录的基础职责。
  5. 学会按第一版页面清单搭出博客项目的路由结构。
  6. 理解page.tsxlayout.tsx和动态路由目录的基础作用。
  7. 知道为什么博客项目需要先抽出公共导航和公共页脚。
  8. 学会用layout.tsx把站点公共外壳连接起来。
  9. 理解children在布局里的意义。
  10. 知道第一版项目初始化时,哪些内容先做占位,哪些细节后面再补。
  11. 掌握一个适合初学者继续扩展的博客项目目录骨架。
  12. 为下一篇继续进入首页、文章列表与本地数据接入做好准备。

一、这一篇到底要完成什么

这一篇我们要做的,不是马上把整个博客做完。

这一篇要完成的是:

先让博客网站“站起来”。

所谓“站起来”,主要是指下面这些事情:

  1. 项目已经创建完成,可以正常运行。
  2. 站点最基础的页面路由已经搭出来。
  3. 公共导航和页脚已经有了统一入口。
  4. layout.tsx已经把整站公共骨架接起来。
  5. 首页、文章列表页、文章详情页、关于页、联系页都已经有基础位置。

这一步非常关键。

因为从综合项目的角度看,它解决的是:

先让“网站结构”成立,而不是先让某个页面局部非常丰富。

二、为什么先搭项目骨架,比先写内容细节更重要

很多人在综合实战刚开始时,最容易做的事是:

先去写一个看起来最有意思的页面。

比如:

  • 先写文章卡片
  • 先写详情页排版
  • 先写首页横幅区

这些当然都重要。

但如果路由和布局还没搭好,后面往往会遇到这些问题:

  1. 页面文件放哪儿开始犹豫。
  2. 导航要不要重写一遍。
  3. 页脚怎么每页都出现。
  4. 页面结构和样式会不会后面推翻重来。

所以更稳的节奏通常是:

先把站点骨架、公共外壳和页面入口搭起来,再往里填具体内容。

你可以把这一步理解成:

先把房子的承重墙和楼梯搭好,再去布置每个房间。

三、第一步:先创建项目

这一版博客项目,我们继续使用:

  • Next.js
  • TypeScript
  • src/目录
  • App Router
  • CSS Modules + 全局样式

如果你使用pnpm,一个很适合当前阶段的初始化命令可以这样写:

pnpmcreate next-app personal-blog\--ts\--eslint\--app\--src-dir\--use-pnpm\--import-alias"@/*"

1. 如果你是交互式创建,关键选项怎么选

如果创建过程中出现交互式问题,当前阶段建议这样选:

  1. TypeScript:Yes
  2. ESLint:Yes
  3. Tailwind CSS:No
  4. src/directory:Yes
  5. App Router:Yes
  6. 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.ts

1.src/app/layout.tsx是什么

它是整站最基础的公共布局入口。

后面我们的:

  • 页头
  • 页脚
  • 全局结构

都会慢慢接到这里。

2.src/app/page.tsx是什么

它对应网站首页,也就是:

/

3.src/app/globals.css是什么

它负责全局基础样式,例如:

  • 字体
  • 背景
  • 链接默认样式
  • 通用容器规则

4.public/是什么

它适合放:

  • 站点图片
  • 图标
  • 文章封面图

也就是那些:

会被页面直接引用的静态资源。

五、第二步:先把第一版路由目录搭出来

上一章我们已经明确了第一版最重要的五个页面:

  1. 首页
  2. 文章列表页
  3. 文章详情页
  4. 关于页
  5. 联系页

所以这一章最关键的动作之一,就是把这些页面先变成真实的目录结构。

一个适合第一版的src/app路由骨架可以先这样搭:

src/app/ ├── layout.tsx ├── page.tsx ├── posts/ │ ├── page.tsx │ └── [slug]/ │ └── page.tsx ├── about/ │ └── page.tsx └── contact/ └── page.tsx

1. 这几个目录分别对应什么地址

你可以先建立下面这组直觉:

  • src/app/page.tsx对应/
  • src/app/posts/page.tsx对应/posts
  • src/app/posts/[slug]/page.tsx对应/posts/某篇文章标识
  • src/app/about/page.tsx对应/about
  • src/app/contact/page.tsx对应/contact

2. 为什么先把目录搭出来很重要

因为它会帮你立刻把这些问题变清楚:

  1. 网站到底有哪些页面
  2. 页面之间的跳转路径是什么
  3. 哪些页面是静态入口,哪些页面是详情页入口

六、为什么文章详情页要用[slug]

博客项目里的文章详情页,不会只有一篇文章。

它通常是:

多篇文章共用同一个详情页结构,只是内容不同。

这时就很适合使用动态路由目录:

[slug]

1.slug可以先怎么理解

你可以先把它理解成:

一篇文章在 URL 里的唯一标识。

例如:

  • react-basic
  • nextjs-routing
  • typescript-generics

它们分别可以对应这样的网址:

/posts/react-basic /posts/nextjs-routing /posts/typescript-generics

2. 为什么博客项目特别适合用这种方式

因为它天然符合:

同一类内容很多条,每条都有自己的详情页。

所以这一章虽然还不会把详情页数据全部写满,但我们要先把这条路由骨架搭出来。

七、先让每个页面“占住位置”

综合项目刚开始时,一个非常稳的做法是:

先让每个页面都有一个基础占位版本。

也就是说,先让这些页面都能打开,再逐步往里面填内容。

例如首页可以先写成:

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. 这段代码最关键的点是什么

不是样式,而是结构:

  1. Logo 区域有了
  2. 导航区域有了
  3. 导航来自统一配置

2. 为什么Link很重要

因为在 Next.js 项目里,页面之间跳转通常要优先使用:

Link

它比直接写普通超链接更符合框架主线。

十、第五步:抽出SiteFooter

页脚和页头一样,也是很典型的公共结构。

第一版页脚不需要很复杂。

只要先把这些信息放上去,就已经非常有价值:

  1. 网站名称
  2. 一句简短说明
  3. 版权或年份信息

例如:

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. 这段代码里最值得先看懂什么

先看懂这四个点就够了:

  1. 全局样式从这里引入
  2. 页头和页脚从这里统一挂上
  3. main区域是页面主体
  4. 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. 当前阶段最重要的不是样式多复杂

而是:

站点整体节奏开始统一。

十四、全局样式第一版先管什么

这一章我们不追求把所有视觉细节都定死。

但全局样式里,第一版至少可以先管下面几件事:

  1. body的默认背景、文字颜色和字体
  2. 链接默认样式
  3. 站点最大宽度容器
  4. 页头、页脚基础留白
  5. 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. 文章卡片完整样式
  3. 详情页正文排版细节
  4. 联系表单提交逻辑
  5. 图片优化细节

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. 当前阶段不需要把所有目录一次填满

目录先留出来,不代表现在每个目录都必须有很多文件。

更重要的是:

你已经先把项目往清楚的方向搭起来了。

十八、开发过程中怎么验证这一步有没有搭好

这一章的成果,其实很适合通过最基础的方式快速验证。

你可以在项目启动后,逐个检查这些地址:

  1. /
  2. /posts
  3. /about
  4. /contact

如果这些页面都能打开,并且都共用了同一个页头和页脚,那就说明:

路由骨架和公共布局已经搭成功了。

1. 当前阶段验证的重点是什么

不是页面多漂亮,而是:

  1. 地址能否对应正确页面
  2. 布局是否统一生效
  3. 页面主体内容是否能被children正常替换

2. 为什么这种“小验证”很重要

因为综合项目最怕的是一路猛写,到后面才发现骨架一开始就有问题。

现在这样小步确认,会稳很多。

十九、这一章最容易踩的几个坑

这一节建议你认真看。

因为博客项目刚起步时,很多问题看起来不大,但后面会反复拖慢你。

1. 坑一:项目初始化选项和技术路线不一致

例如上一章明明决定先用 CSS Modules,却创建时又把样式方案弄成完全另一套。

这会让后面学习主线变乱。

2. 坑二:路由目录一开始就随手乱放

这样后面一多页面,就很容易:

  • 不知道文件放哪儿
  • 静态页和详情页混在一起

3. 坑三:页头和页脚直接复制到每个页面

这样短期看方便,长期会非常难改。

4. 坑四:layout.tsx里塞太多页面专属逻辑

布局层更适合放公共结构,不适合一开始就混入大量页面独有内容。

5. 坑五:路由骨架没搭稳,就急着做复杂样式和交互

这样后面返工的概率会很高。

二十、本章实践练习

这一章的练习重点,是把“博客项目第一版骨架”真正搭起来。

1. 练习 1:创建项目并跑起来

请你用pnpm create next-app创建一个新的博客项目,并确认:

  1. TypeScript 已开启
  2. App Router 已开启
  3. 使用了src/目录
  4. 项目可以通过pnpm dev正常运行

这个练习的重点是:

把技术选型真正落到一个可运行项目里。

2. 练习 2:搭出第一版路由目录

请你根据这一章内容创建:

  • 首页
  • 文章列表页
  • 文章详情页动态路由
  • 关于页
  • 联系页

这个练习会帮助你真正建立:

页面清单要变成真实目录结构,项目主线才算开始成立。

3. 练习 3:抽出SiteHeaderSiteFooter

请你把公共导航和页脚分别抽成组件,并通过layout.tsx统一挂载。

这个练习会帮助你真正理解:

公共结构应该放公共层,而不是写在每个页面里。

4. 练习 4:给所有页面先写职责占位

请你让首页、列表页、详情页、关于页、联系页都先有一份最小占位内容。

这个练习的重点是:

先让每个页面的职责站住,再逐步填充真实内容。

二十一、学习重点提示

这一章请你重点记住下面这些话:

  1. 综合项目开始落地时,最重要的不是马上写很多内容,而是先把项目骨架搭稳。
  2. 项目初始化、路由目录和公共布局,是博客项目后面能不能写得顺的基础。
  3. 第一版先把页面入口搭出来,比一开始就死磕页面细节更稳。
  4. layout.tsx的核心价值,是把公共结构统一挂起来,让页面只关心自己的主体内容。
  5. children表示当前路由页面会被填进布局里的那块变化区域。
  6. 导航配置、页头组件、页脚组件尽早抽出来,后面会省很多重复劳动。
  7. 骨架阶段先做占位页,是一种非常有效的小步推进方式。
  8. 先主结构,再主内容,再补交互和样式细节。

如果你只记一句话,请记住:

第五阶段综合实战真正开始落地时,最关键的不是谁先写出最花的页面,而是谁先把项目初始化、路由骨架和公共布局搭清楚。

二十二、本章小结

这一章,我们正式把第五阶段综合实战从“需求分析与技术选型”推进到了“项目骨架真正落地”的阶段。

你已经理解了:

  • 为什么博客项目一开始要先搭骨架
  • 项目初始化时哪些选项更适合当前这次实战
  • 第一版页面清单应该怎样落成真实路由目录
  • 为什么文章详情页适合使用[slug]动态路由
  • 为什么页头和页脚应该尽早抽成公共组件
  • layout.tsxchildren在站点骨架里分别扮演什么角色
  • 全局样式第一版最值得先管哪些基础内容
  • 为什么这一阶段先做占位页是一个更稳的推进方式

更重要的是,你开始真正建立一种非常关键的项目意识:

综合项目不是从某个漂亮模块开始,而是从项目地基开始。

这一步非常关键。

因为从这里开始,你已经不只是在学 Next.js 的概念,而是在开始真正进入:

个人博客项目第一版骨架的搭建阶段。

二十三、课后思考题

请你认真思考下面这些问题:

  1. 为什么综合项目一开始,先搭路由和布局会比先写某个局部页面更稳?
  2. 为什么第一版博客项目适合先让每个页面“占住位置”?
  3. 为什么页头和页脚尽早抽成公共组件会更省事?
  4. layout.tsxchildren的关系,最朴素的理解是什么?
  5. 为什么动态路由[slug]特别适合文章详情页?
  6. 为什么项目初始化阶段不适合一开始就做太多页面样式和交互细节?
  7. 你觉得当前这套博客项目骨架里,哪一部分最容易在刚开始时被忽略?为什么?

建议你把这些问题用自己的话写下来。

只要你能把这些问题讲清楚,说明你已经真正开始进入第五阶段综合实战的落地主线了。

二十四、下一篇预告

下一篇我们会继续推进第五阶段综合实战,进入:

第五阶段综合实战:博客首页、文章列表与本地文章数据接入

到那时,你会开始真正把这一篇搭好的路由和布局骨架填起来:

  • 本地文章数据怎么组织
  • 首页怎么展示推荐内容
  • 文章列表页怎么渲染文章卡片
  • 内容页主线怎么真正开始跑起来

也就是说,下一篇开始,我们会从“项目初始化、路由设计与公共布局搭建”继续走到:

个人博客项目第一版内容展示主线的真正实现。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询