用 AI 搭一个可维护的技术博客
为什么用 AI 做这个博客

我想做一个长期写 AI、开发和工具实验的博客。需求并不复杂:页面要轻,文章要好维护,部署成本要低,后续还能继续扩展。
这类项目很适合用 AI 辅助开发。它不需要从零发明复杂架构,但有很多重复工作:组件拆分、样式调整、Markdown 渲染、SEO 配置、部署脚本。AI 能加速这些部分,但最终的结构、取舍和验收仍然需要人工把关。
技术选型
最终采用的是一套偏轻量的前端方案:
| 层面 | 技术 | 选择原因 |
|---|---|---|
| 构建工具 | Vite | 启动快,适合静态站点 |
| UI 框架 | React | 组件化清晰,生态成熟 |
| 样式 | Tailwind CSS | 调整效率高,适合快速迭代视觉稿 |
| 路由 | React Router | 支持文章详情页等 SPA 路由 |
| Markdown | react-markdown + remark-gfm | 支持表格、代码块等常用写作格式 |
| 代码高亮 | react-syntax-highlighter | 能覆盖技术文章里的多语言代码 |
| SEO | react-helmet-async | 每个页面可单独设置元信息 |
| 部署 | Nginx + HTTPS | 静态资源托管,成本低 |
项目结构保持简单:
src/
├── components/
│ ├── Header.jsx
│ ├── Footer.jsx
│ ├── PostCard.jsx
│ └── SEO.jsx
├── pages/
│ ├── Home.jsx
│ ├── Post.jsx
│ ├── News.jsx
│ ├── About.jsx
│ ├── Products.jsx
│ └── Resources.jsx
├── data/
│ └── posts.js
├── posts/
│ └── *.md
├── App.jsx
├── main.jsx
└── index.css
AI 辅助开发的实际节奏
我没有让 AI 一次性生成完整项目,而是分阶段推进:
1. 建立项目骨架和全局样式
2. 完成首页、文章页、基础组件
3. 接入 Markdown 内容系统
4. 增加代码高亮、目录、SEO
5. 扩展 About / News / Products / Resources 页面
6. 构建、部署、修复线上问题
这个节奏比“直接生成整个网站”稳定得多。每一步都可以运行、预览、检查,再进入下一步。
我的经验是:AI 适合生成初稿,不适合替你做最终判断。尤其是样式、交互和数据层逻辑,需要不断压缩范围、明确验收标准。
内容系统:Markdown 驱动
博客文章全部放在 src/posts/ 里,每篇文章由 Frontmatter 和正文组成:
---
slug: article-url-slug
title: "文章标题"
date: 2026-04-30
tags: ["工程实践"]
category: blog
coverImage: "https://..."
excerpt: "文章摘要"
---
## 正文内容
Markdown 格式的文章正文...
构建时通过 Vite 自动收集所有 Markdown 文件:
const postModules = import.meta.glob('/src/posts/*.md', {
query: '?raw',
import: 'default',
eager: true,
})
我一开始考虑过用 gray-matter 解析 Frontmatter,但它更适合 Node.js 环境。为了避免客户端构建兼容性问题,最后写了一个只覆盖当前需求的轻量解析器:
function parseFrontmatter(raw) {
const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/)
if (!match) return { data: {}, content: raw }
const frontmatter = match[1]
const content = match[2]
const data = {}
frontmatter.split('\n').forEach((line) => {
const colonIndex = line.indexOf(':')
if (colonIndex === -1) return
const key = line.slice(0, colonIndex).trim()
let value = line.slice(colonIndex + 1).trim()
if (value.startsWith('[') && value.endsWith(']')) {
value = value
.slice(1, -1)
.split(',')
.map((s) => s.trim().replace(/^["']|["']$/g, ''))
}
if (/^["'].*["']$/.test(value)) {
value = value.slice(1, -1)
}
data[key] = value
})
return { data, content }
}
这不是通用 YAML 解析器,但对当前文章元数据足够,也减少了依赖。
文章页:阅读体验比功能堆叠重要
技术博客的文章页至少要解决三件事:代码可读、长文可导航、移动端不拥挤。
代码块用 react-syntax-highlighter 渲染:
code({ inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
style={oneLight}
language={match[1]}
PreTag="div"
customStyle={{ borderRadius: '12px', fontSize: '0.85rem' }}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code className={className} {...props}>{children}</code>
)
}
目录则从 Markdown 的 h2 / h3 中提取:
function extractHeadings(content) {
const headings = []
content.split('\n').forEach((line) => {
const match = line.match(/^(#{2,3})\s+(.+)$/)
if (match) {
headings.push({
level: match[1].length,
text: match[2].trim(),
id: makeId(match[2]),
})
}
})
return headings
}
后续又对目录做过一次调整:不再让顶部导航固定在屏幕上,同时让文章侧边目录可以独立滚动。这样长文读到中后段时,仍然可以点到下方章节。
SEO 与分享信息
每个页面通过 SEO 组件设置标题、描述、canonical 和 Open Graph 信息:
<Helmet>
<title>{fullTitle}</title>
<meta name="description" content={desc} />
<link rel="canonical" href={url} />
<meta property="og:title" content={fullTitle} />
<meta property="og:description" content={desc} />
<meta property="og:image" content={ogImage} />
<meta name="twitter:card" content="summary_large_image" />
</Helmet>
站点层面还保留了这些文件:
| 文件 | 作用 |
|---|---|
sitemap.xml |
给搜索引擎提供索引入口 |
rss.xml |
提供订阅源 |
robots.txt |
控制爬虫访问规则 |
SEO 没有什么神奇技巧,关键是每篇文章的标题、摘要、封面和 canonical 不要缺失。
遇到的几个实际问题
Frontmatter 解析库不适合客户端构建
gray-matter 在 Node.js 里很好用,但放进 Vite 客户端构建后可能遇到 fs、Buffer 等兼容性问题。这个项目的元数据格式很固定,自己写一个小解析器反而更稳。
SPA 路由刷新 404
React Router 的 /post/xxx 是前端路由,服务器上没有对应物理文件。Nginx 需要回退到 index.html:
location / {
try_files <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.0278em;">r</span><span class="mord mathnormal">i</span></span></span></span>uri/ /index.html;
}
GFM 表格没有渲染
react-markdown 默认不包含 GitHub Flavored Markdown。要渲染表格,需要接入 remark-gfm,再补充表格样式。
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{post.content}
</ReactMarkdown>
AI 生成代码仍会漏 import
这类小错误很常见,比如使用了某个图标组件,却忘记在顶部 import。构建或运行时通常能发现,但最好在每次改完后都执行一次 build。
部署方式
部署链路保持简单:本地构建,上传静态文件,Nginx 托管。
本地 npm run build
↓
上传 dist
↓
服务器解压到 Web 根目录
↓
Nginx 提供静态访问
Nginx 配置重点是 HTTPS、静态缓存、Gzip 和 SPA 回退:
server {
listen 443 ssl http2;
server_name techloop.online www.techloop.online;
root /var/www/blog;
index index.html;
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
gzip_min_length 1000;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ {
expires 6M;
add_header Cache-Control "public, immutable";
}
location / {
try_files <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">u</span><span class="mord mathnormal" style="margin-right:0.0278em;">r</span><span class="mord mathnormal">i</span></span></span></span>uri/ /index.html;
}
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
}
HTTPS 使用 Let's Encrypt:
sudo certbot --nginx -d techloop.online -d www.techloop.online
对 Vibe Coding 的实际感受
AI 确实提高了搭建速度,尤其是页面初稿、组件拆分和样式迭代。但它并不会自动保证产品质量。
我认为比较有效的方式是:
- 先明确页面目标,再让 AI 生成初版。
- 每次只改一组问题,不要混在一起改。
- 代码能跑只是第一步,还要检查阅读体验和边界情况。
- 关键逻辑自己看一遍,尤其是数据加载、路由和部署配置。
这次博客项目的价值不在于“AI 几小时做完网站”,而在于形成了一套可持续维护的内容系统。后续新增文章,只需要写 Markdown;要扩展页面,也有现成的视觉和组件基础。
后续计划
接下来更值得投入的是内容和体验,而不是继续堆功能:
| 方向 | 说明 |
|---|---|
| 全文搜索 | 文章数量上来后接入 Pagefind 或 Algolia |
| 评论系统 | 可考虑 Giscus,保持低维护成本 |
| 深色模式 | 用 CSS 变量统一管理颜色 |
| RSS 完善 | 让订阅源与文章数据自动同步 |
| 内容编辑流程 | 继续优化 Decap CMS 或本地写作流程 |
AI 可以加快实现速度,但博客最终能不能留下来,还是取决于内容是否持续更新、结构是否容易维护。
See also
- 一次完整的 WSL2 安装排障:从 BIOS、TPM 判断到 Windows 11 修复安装 2026-07-07
- 把一个 SPA 博客补成可预渲染、可同步、可持续部署 2026-05-29
- 把宿舍 Windows 主机改成可远程训练的 WSL 工作站 2026-05-27
- 把每日科技日报改成服务器自运行 2026-05-26
- Chrome 一打开就跳到 360 导航页?按这份手册一步步修复 2026-05-20