蔡穗霞博客2026最新实战:5步搭完个人技术站
别再对着官方文档发呆,那些几千页的长文确实让人抓不住重点。想搞懂蔡穗霞博客这类个人技术站到底怎么从零跑通,还得看2026最新的实战拆解。我直接把坑都踩平了,你照着抄就行,三行代码就能让页面动起来,拒绝空谈理论。
项目目标与需求拆解
很多人一上来就纠结选什么框架,其实核心目标就两个:静态化部署和内容易维护。
蔡穗霞博客的定位很清晰,就是做技术干货分享。这类站点不需要复杂的后端逻辑,用户只需要看文章、看代码块、看图片。所以我们的技术选型必须极简单。
为什么选这套组合?
- Next.js 14+:目前前端生态里静态生成能力最强的框架,2026年依然是主流。它能把React组件直接编译成HTML,加载速度极快,SEO友好。
- MDX:允许你在Markdown里直接写React组件。比如你想在文章里插一个可运行的代码演示,或者一个特殊的警告框,用纯Markdown做不到,用MDX就可以。
- Tailwind CSS:原子化CSS,不用写一堆复杂的样式文件,类名即样式,开发效率极高。
避坑提示: 别一上来就用Jekyll或Hexo。虽然它们更简单,但在2026年的技术环境下,生态支持不如Next.js丰富。特别是当你想加入“代码高亮”、“暗色模式切换”、“目录自动生成”这些高级功能时,React生态的优势就体现出来了。
核心指标定义:
- LCP(最大内容绘制)< 2.5s
- CLS(累积布局偏移)< 0.1
- TBT(总阻塞时间)< 200ms
这三个指标是衡量博客性能的黄金标准。如果达不到,说明你的代码有问题,或者资源加载策略不对。
目录结构规划
清晰的目录结构是项目可维护性的基石。很多人喜欢把所有东西扔进一个文件夹,那是自寻死路。
推荐结构如下:
project-root/
├── public/ # 静态资源,如favicon, logo
├── src/
│ ├── app/ # Next.js 14 App Router核心目录
│ │ ├── layout.tsx # 根布局,包含Header和Footer
│ │ ├── page.tsx # 首页
│ │ ├── about/
│ │ │ └── page.tsx # 关于页面
│ │ └── blog/
│ │ ├── page.tsx # 博客列表页
│ │ └── [slug]/
│ │ └── page.tsx # 博客详情页(动态路由)
│ ├── components/ # 通用UI组件
│ │ ├── Header.tsx
│ │ ├── Footer.tsx
│ │ ├── CodeBlock.tsx # 代码块组件
│ │ └── TableOfContents.tsx # 目录组件
│ ├── lib/ # 工具函数
│ │ ├── utils.ts
│ │ └── mdx.ts # MDX解析逻辑
│ └── styles/
│ └── globals.css # 全局样式
├── content/ # 文章存放目录(纯Markdown/MDX)
│ ├── 2026-nextjs-tips.mdx
│ └── seo-optimization.mdx
├── package.json
├── tailwind.config.ts
└── next.config.js
关键点解析:
app目录:这是Next.js 14的核心。不同于旧的pages目录,app路由基于文件系统,更直观。content目录:文章全部放在这里。为什么不在src里?因为文章是内容,代码是逻辑,物理隔离便于后续做静态站点生成(SSG)时的缓存管理。[slug]动态路由:这是博客详情页的关键。Next.js会自动根据content目录下的文件名生成路由。
常见错误:
不要手动在app目录下创建每个文章的文件夹。比如app/blog/nextjs-tips/page.tsx。这样做会导致每写一篇文章就要新建一个文件夹,维护成本极高。必须使用动态路由[slug],通过代码自动读取content目录下的文件。
核心代码实现
这部分是硬菜。我们不讲虚的,直接上代码,并逐行拆解。
1. 读取Markdown内容
在src/lib/mdx.ts中,我们需要一个函数来读取content目录下的所有MDX文件。
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import { MDXRemote } from "next-mdx-remote/rsc";
import { compileMDX } from "next-mdx-remote/client";// 定义文章类型
export type Post = {slug: string;title: string;date: string;description: string;content: string;
};// 获取所有文章的slug
export function getAllPostSlugs() {const postsDirectory = path.join(process.cwd(), "content");return fs.readdirSync(postsDirectory).filter((file) => file.endsWith(".mdx")).map((file) => file.replace(/\.mdx$/, ""));
}// 获取单篇文章详情
export function getPostBySlug(slug: string) {const postsDirectory = path.join(process.cwd(), "content");const fullPath = path.join(postsDirectory, `${slug}.mdx`);// 读取文件内容const fileContents = fs.readFileSync(fullPath, "utf8");// 解析frontmatter(标题、日期等元数据)const { data, content } = matter(fileContents);return {slug,title: data.title,date: data.date,description: data.description,content,};
}
逐行讲解:
gray-matter:专门用来解析Markdown头部的YAML元数据(如title,date)。process.cwd():获取当前工作目录,确保在开发环境和生产环境都能正确找到文件。- 注意:
next-mdx-remote在Server Components中的用法有变化,这里简化展示,实际项目中需配合next-mdx-remote/rsc使用。
2. 动态路由页面
在src/app/blog/[slug]/page.tsx中,我们实现文章详情页。
import { notFound } from "next/navigation";
import { getAllPostSlugs, getPostBySlug } from "@/lib/mdx";
import { MDXRemote } from "next-mdx-remote/rsc";// Next.js 14 静态生成数据
export function generateStaticParams() {return getAllPostSlugs().map((slug) => ({slug,}));
}export default async function BlogPost({ params }: { params: { slug: string } }) {// 获取文章数据const post = getPostBySlug(params.slug);// 如果文章不存在,返回404if (!post) {notFound();}return (<article className="max-w-2xl mx-auto p-6"><h1 className="text-3xl font-bold mb-4">{post.title}</h1><p className="text-gray-500 mb-8">{post.date}</p>{/* 渲染MDX内容 */}<MDXRemote source={post.content} /></article>);
}
关键细节:
generateStaticParams:这是SSG的核心。Next.js会在构建时调用这个函数,为每个slug生成一个独立的HTML文件。这意味着用户访问文章时,不需要等待服务器计算,直接返回HTML,速度极快。async:因为读取文件是异步操作,组件必须标记为异步。notFound():Next.js内置函数,当文章不存在时,自动触发404页面。
3. 代码高亮组件
博客的核心是代码。默认的Markdown代码块很难看。我们需要自定义CodeBlock组件。
在src/components/CodeBlock.tsx中:
import { Prism } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";export default function CodeBlock({ code, language }: { code: string; language: string }) {return (<div className="relative group">{/* 复制按钮 */}<button onClick={() => navigator.clipboard.writeText(code)}className="absolute top-2 right-2 p-1 bg-gray-700 rounded text-xs opacity-0 group-hover:opacity-100 transition">Copy</button><Prism language={language} style={oneDark} className="text-sm rounded-lg">{code}</Prism></div>);
}
避坑:
react-syntax-highlighter包比较大。如果使用Next.js,务必使用动态导入dynamic来加载,避免首屏加载巨大的JS包,影响LCP指标。
运行与测试
代码写完了,怎么确保它是对的?
1. 本地开发
npm run dev
打开http://localhost:3000。
- 检查点1:首页是否正常加载?
- 检查点2:点击任意文章链接,是否跳转到对应内容?
- 检查点3:刷新文章页面,URL是否变化?内容是否保留?(SSG特性验证)
2. 性能测试
使用Chrome DevTools的Lighthouse面板。
- 打开博客首页。
- 运行Lighthouse分析。
- 查看Performance分数。
常见性能杀手:
- 图片未优化:使用Next.js的
<Image />组件,它会自动进行WebP格式转换和懒加载。import Image from "next/image"; <Image src="/cover.jpg" alt="Cover" width={800} height={400} /> - 字体加载阻塞:确保字体使用
display: swap,避免FOIT(不可见文本闪烁)。
3. SEO检查
在MDN Web Docs中,关于语义化HTML的规范指出,<article>标签应包含独立的、可分发的内容。我们的博客详情页已经使用了<article>,这是正确的。
另外,确保每个页面都有唯一的<title>和<meta name="description">。Next.js中,可以通过export const metadata来设置:
export const metadata = {title: post.title,description: post.description,
};
优化扩展与避坑
1. 暗色模式
2026年的博客如果没有暗色模式,会被认为是不专业的。
使用Tailwind CSS的dark类,配合localStorage保存用户偏好。
// 在layout.tsx中
useEffect(() => {const isDark = localStorage.getItem("theme") === "dark";document.documentElement.classList.toggle("dark", isDark);
}, []);
2. 搜索功能
不要一上来就做全文搜索。对于个人博客,一个简单的客户端过滤就足够了。
在博客列表页,使用React的useMemo对文章标题进行过滤。
const filteredPosts = useMemo(() => {if (!searchTerm) return posts;return posts.filter((post) => post.title.toLowerCase().includes(searchTerm.toLowerCase()));
}, [searchTerm, posts]);
3. 常见坑点
- Hydration Error:如果服务器渲染的HTML和客户端JavaScript生成的DOM不一致,会报错。通常是因为使用了
Date.now()或Math.random()在渲染期间。- 对策:在
useEffect中处理这些动态数据,或者使用suppressHydrationWarning(不推荐,治标不治本)。
- 对策:在
- 图片闪烁:如果图片尺寸未固定,加载时会发生布局偏移(CLS)。
- 对策:始终给
<Image />组件指定width和height属性。
- 对策:始终给
- 依赖地狱:
next-mdx-remote的版本必须与Next.js版本严格匹配。查看官方文档,确保版本兼容。
小结
搭建蔡穗霞博客这类技术站点,核心不在于技术多炫,而在于稳定和易维护。
- Next.js 14 提供了强大的SSG能力,确保性能。
- MDX 让内容创作更灵活。
- Tailwind CSS 让样式开发极速。
你不需要成为架构师,只需要按照这套流程,把每个小模块拼起来。
最后,抛出一个问题:
你在项目里踩过这个坑吗?比如Hydration Error怎么解决的?或者MDX组件里怎么嵌入交互式代码演示?评论区聊聊,咱们互相避雷。