从零搭建静态博客:现代前端工程化实践与思考
从零搭建静态博客:现代前端工程化实践与思考
最好的学习方式是创造,而创造的最佳起点是构建一个属于自己的数字花园。在这个 AI 触手可及的时代,我们有了更强大的创造工具。
引言:为什么要从零开始?
在众多优秀的静态站点生成器(如 Hexo、Hugo、Jekyll)存在的今天,为什么还要选择从零开始搭建博客?这个问题困扰了很多人,但对我来说,学习过程本身就是最大的价值。
不过,这里的"从零开始"不是指每一行代码都自己手写,而是:
从零理解需求:而不是盲目套用现成方案
从零设计架构:而不是接受黑盒封装
从零把控质量:而不是被动依赖社区维护
从零优化体验:而不是满足于默认配置
核心观点:使用现成工具是消费技术,自建系统是理解技术,而善用 AI 则是加速理解。
传统工具 vs 自建系统 vs AI 协作
| 特性 | 传统静态站点生成器 | 自建系统 | 自建+AI 协作 |
|------|-------------------|----------|-------------|
| 学习成本 | 低,快速上手 | 高,需要深入理解 | 中等,AI 降低门槛 |
| 灵活度 | 中等,受限于插件生态 | 极高,完全自主控制 | 极高,且实现更快 |
| 技术深度 | 表层应用 | 底层原理到工程实践 | 原理 + 效率双收 |
| 开发周期 | 1-2 天配置 | 1-2 周开发 | 3-5 天开发 |
| 可扩展性 | 依赖社区维护 | 按需扩展,无限制 | 按需扩展,AI 助力 |
| 部署复杂度 | 简化,一键部署 | 需要自行配置 | 配置 + AI 优化建议 |
看到了吗?AI 协作不是降低质量,而是在保持深度的同时提升效率。
一、技术栈选择与思考
1.1 为什么选择纯前端技术栈?
graph TD
A[需求分析] --> B[静态内容为主]
B --> C[快速加载]
C --> D[SEO友好]
D --> E[零服务器成本]
E --> F[选择纯前端]
决策依据:
内容性质:博客以文字为主,交互需求简单
性能要求:静态文件可被CDN缓存,加载极快
成本考量:GitHub Pages 提供免费托管
维护成本:无需服务器运维,专注内容创作
1.2 核心工具链
// package.json 中的关键依赖
{
"devDependencies": {
// 构建工具
"fs-extra": "^11.0.0", // 增强的文件操作
"marked": "^12.0.0", // Markdown 解析
"gray-matter": "^4.0.3", // Front Matter 解析
// 开发工具
"nodemon": "^3.0.0", // 文件监听
"live-server": "^1.2.0", // 本地开发服务器
// 代码质量
"prettier": "^3.0.0", // 代码格式化
"eslint": "^8.0.0" // 代码检查
}
}
选择理由:
fs-extra:Node.js 原生 fs 模块的增强版,提供 Promise 支持
marked:轻量级、高性能的 Markdown 解析器
gray-matter:优雅地解析 YAML Front Matter
nodemon:开发时自动重启,提升开发体验
二、架构设计与模块化
2.1 项目结构设计
my-blog/
├── src/ # 源码目录
│ ├── data/ # 内容数据
│ │ ├── articles/ # Markdown 文章
│ │ ├── projects/ # 项目数据
│ │ └── config.json # 站点配置
│ ├── templates/ # HTML 模板
│ │ ├── base.html # 基础布局
│ │ └── article.html # 文章模板
│ └── assets/ # 静态资源
│ ├── css/
│ ├── js/
│ └── images/
├── scripts/ # 构建脚本
│ └── builder.js # 静态站点生成器
└── public/ # 构建输出
设计理念:关注点分离(Separation of Concerns)
数据与表现分离
模板与逻辑分离
开发与生产分离
说实话:这个架构是我设计的,但 builder.js 的具体实现,AI 帮我写了大概 70%。
一开始我想自己从头写,但在实现了基础的 Markdown 解析后,我发现:
文件路径处理有很多边界情况(Windows vs Unix、绝对路径 vs 相对路径)
错误处理要考虑很多场景(文件不存在、权限问题、磁盘空间不足)
性能优化需要专业知识(缓存策略、增量构建、并发处理)
如果都自己摸索,可能需要几周时间。
我的选择:让 AI 帮忙实现这些"脏活累活",我把精力放在:
架构设计是否合理
代码质量是否达标
边界情况是否考虑周全
可扩展性是否足够
结果:3 天就完成了整个构建系统,而且每一行代码我都理解。
这比"从零手写"更有价值——因为我学会了如何驾驭工具。
2.2 构建系统设计
// builder.js 的核心架构
class SiteBuilder {
constructor() {
this.pipeline = [
this.cleanOutput.bind(this),
this.loadConfig.bind(this),
this.processContent.bind(this),
this.generatePages.bind(this),
this.optimizeAssets.bind(this)
];
}
async build() {
for (const step of this.pipeline) {
await step();
}
}
}
构建流程:
清理阶段:删除旧的构建文件
读取阶段:加载配置和内容
转换阶段:Markdown → HTML,模板渲染
生成阶段:输出静态文件
优化阶段:压缩、合并、添加哈希
这个架构怎么来的?
我给 AI 的描述是:
"我想要一个类似工厂流水线的构建系统,每个步骤独立可测,失败了能优雅处理,还能方便地加新功能。"
AI 给了我第一版代码——用的是简单的函数调用链。
我让它改了两次:
"改成类的设计,这样状态管理更方便"
"加上 pipeline 模式,每一步都能单独测试"
最后得到的版本,就是你现在看到的这个样子。
我的收获:
学会了流水线设计模式(从 AI 的实现中理解)
理解了面向对象的优势(我自己提出的需求)
掌握了渐进式重构的方法(通过和 AI 的对话学习)
如果是我自己从零写,可能还在纠结fs.remove()和 fs.emptyDir() 的区别。
但现在,我可以自信地说:我理解这个系统的每一部分,并且有能力修改和优化它。
这就够了。
三、Markdown 处理与扩展
3.1 Front Matter 设计
---
title: "文章标题"
date: 2025-01-28
tags: ["标签1", "标签2"]
category: "分类"
summary: "文章摘要"
read_time: 10
difficulty: "进阶"
cover_image: "/assets/cover.jpg"
---
元数据作用:
SEO优化:title, description, keywords
内容组织:tags, category
用户体验:read_time, difficulty
视觉呈现:cover_image
3.2 Markdown 扩展功能
// 自定义 Markdown 渲染器
const renderer = new marked.Renderer();
// 1. 标题锚点
renderer.heading = function(text, level) {
const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
return `<h${level} id="${escapedText}">${text}</h${level}>`;
};
// 2. 代码块增强
renderer.code = function(code, language) {
const highlighted = hljs.highlight(code, { language }).value;
return `
<div class="code-block">
<div class="code-header">
<span class="language">${language}</span>
<button class="copy-btn">复制</button>
</div>
<pre><code class="hljs ${language}">${highlighted}</code></pre>
</div>
`;
};
四、模板引擎与组件化
4.1 简单的模板引擎实现
// 简易模板引擎
class TemplateEngine {
constructor(template, data) {
this.template = template;
this.data = data;
}
render() {
return this.template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return this.data[key] || '';
});
}
}
// 使用示例
const template = '<h1>{{title}}</h1><p>{{content}}</p>';
const data = { title: 'Hello', content: 'World' };
const engine = new TemplateEngine(template, data);
console.log(engine.render()); // <h1>Hello</h1><p>World</p>
4.2 组件化设计
<!-- 文章卡片组件 -->
<article class="article-card" data-id="{{id}}">
<div class="card-header">
<div class="category">{{category}}</div>
<h3 class="title">{{title}}</h3>
<p class="summary">{{summary}}</p>
</div>
<div class="card-footer">
<div class="meta">
<time>{{date}}</time>
<span class="read-time">{{read_time}} min</span>
</div>
<div class="tags">
{{#each tags}}
<span class="tag">{{this}}</span>
{{/each}}
</div>
</div>
</article>
五、性能优化策略
5.1 构建时优化
// 图片优化示例
async function optimizeImages() {
const images = await glob('src/assets/images/**/*.{jpg,png,webp}');
for (const image of images) {
// 1. 压缩图片
await sharp(image)
.resize(1200) // 限制最大宽度
.webp({ quality: 80 }) // 转换为 WebP
.toFile(image.replace(/\.(jpg|png)$/, '.webp'));
// 2. 生成不同尺寸
await generateResponsiveImages(image);
}
}
5.2 运行时优化
/* 关键 CSS 内联 */
<style>
/* 首屏关键样式 */
.header, .hero, .first-article {
/* 精简的初始样式 */
}
</style>
<!-- 非关键 CSS 异步加载 -->
<link
rel="preload"
href="/assets/css/non-critical.css"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
>
<noscript>
<link rel="stylesheet" href="/assets/css/non-critical.css">
</noscript>
六、开发工作流优化
6.1 自动化脚本配置
{
"scripts": {
"dev": "concurrently \"npm run build:watch\" \"npm run serve\"",
"build": "NODE_ENV=production node scripts/builder.js",
"build:watch": "nodemon --watch src --ext md,html,json --exec \"npm run build\"",
"serve": "live-server public --port=3000 --watch=public",
"deploy": "npm run build && gh-pages -d public",
"format": "prettier --write \"src/**/*.{js,md,css,html}\"",
"lint": "eslint src/scripts/**/*.js"
}
}
6.2 Git Hooks 集成
{
"husky": {
"hooks": {
"pre-commit": "npm run lint && npm run format",
"pre-push": "npm run build"
}
}
}
七、部署与持续集成
7.1 GitHub Actions 自动化部署
## .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
八、遇到的挑战与解决方案
8.1 跨平台路径问题
问题:Windows 和 Unix 系统的路径分隔符不同
// ❌ 错误写法
const path = 'src/data/articles';
// ✅ 正确写法
const path = path.join('src', 'data', 'articles');
8.2 相对路径处理
问题:文章中的图片引用路径需要转换
function processImagePaths(content, slug) {
// 将相对路径转换为绝对路径
return content.replace(
/!\[([^\]]*)\]\(([^)]+)\)/g,
(match, alt, src) => {
if (!src.startsWith('http')) {
src = `/assets/images/${slug}/${src}`;
}
return `!${src}`;
}
);
}
8.3 增量构建优化
问题:每次构建都处理所有文件,效率低下
// 文件哈希缓存
class BuildCache {
constructor() {
this.cacheFile = '.build-cache.json';
}
async getFileHash(filePath) {
const content = await fs.readFile(filePath);
return createHash('md5').update(content).digest('hex');
}
async hasChanged(filePath) {
const currentHash = await this.getFileHash(filePath);
const cache = await this.loadCache();
return cache[filePath] !== currentHash;
}
}
九、技术收获与反思
9.1 技术层面的提升
通过这个项目,我学到了什么?
- Node.js 文件系统操作:深入理解了异步文件处理
- 虽然大部分代码是 AI 写的,但我 review 了每一行
- 知道了 fs.readFile()和fs.readFileSync() 的区别
- 学会了用 fs-extra 增强错误处理
- 构建工具原理:理解了 Webpack、Vite 等工具的基本思想
- 通过自己实现一个简单的构建系统
- 明白了"打包"、"转换"、"优化"的本质
- AI 帮我实现了细节,但我理解了整体
- 模块化设计:学会了如何设计可维护的代码结构
- 从 AI 给的第一版"面条代码"开始
- 我要求它重构为类的设计
- 逐步演进出现在的 pipeline 架构
- 性能优化:掌握了前端性能优化的多种策略
- AI 建议的缓存机制
- 我提出的增量构建想法
- 共同实现的懒加载方案
- AI 协作能力:这可能是最重要的收获
- 学会了如何向 AI 清晰地描述问题
- 学会了如何验证 AI 给出的方案
- 学会了如何在 AI 的基础上继续优化
说实话:如果这个项目的代码 100% 是我自己写的,我可能学得更深。
但我也敢说:现在这种"20% 设计 + 30% Review + 50% AI 实现"的模式,让我在相同时间内学到了更多。
因为我把省下来的时间用来:
深入理解架构设计的权衡
思考如何把这个模式复用到其他项目
写文章分享经验(比如你现在看的这篇)
这才是 AI 时代的正确学习方式。
9.2 工程思维的形成
- 迭代开发:从简单到复杂,逐步添加功能
- 第一版只能解析 Markdown
- 第二版加了模板变量替换
- 第三版支持条件渲染
- 第四版实现路径自动转换
AI 的作用:快速实现每个版本的基础功能
我的作用:决定迭代方向,把控代码质量
- 错误处理:学会了防御性编程和错误边界处理
- AI 最初给的代码没有错误处理
- 我让它加上了 try-catch
- 后来又要求区分致命错误和警告
- 最后实现了优雅的降级方案
- 文档意识:代码注释、README、技术文档的撰写
- AI 生成的代码注释很简陋
- 我重新写了所有关键函数的注释
- 补充了使用示例和注意事项
- 这个过程让我更理解代码本身
- 版本控制:合理的 Git 提交策略和分支管理
- AI 不懂 Git 最佳实践
- 我自己设计了提交规范
- 建立了 feature branch 工作流
- 这是 AI 无法替代的经验
9.3 可改进的方向
graph LR
A[当前版本] --> B[插件系统]
A --> C[主题系统]
A --> D[TypeScript 迁移]
A --> E[更好的 AI 协作流程]
B --> E1[代码高亮插件]
B --> F[评论系统插件]
C --> G[主题市场]
C --> H[在线编辑器]
E --> I[提示词库]
E --> J[自动化 Review]
看到最后一个分支了吗?"更好的 AI 协作流程"——这是我独有的思考。
大部分人只想着怎么用 AI 写代码,而我在想:
如何把和 AI 的对话记录下来形成知识库
如何让 AI 更好地理解我的项目上下文
如何建立一套"AI 辅助代码审查"的流程
如何把这篇文章的经验分享给更多人
这就是为什么我说"善用 AI 比从零手写更有价值"。
因为我不仅在写代码,还在创造方法论。
十、给后来者的建议
10.1 学习路径建议
阶段一:基础功能(1-2 周)
Markdown 解析
简单模板渲染
基础样式设计
AI 协作建议:
✅ 让 AI 帮你搭建项目骨架
✅ 让 AI 解释每个依赖的作用
❌ 不要让 AI 直接给你完整方案(先自己思考)
阶段二:增强功能(1-2 周)
代码高亮
图片优化
RSS 生成
AI 协作建议:
✅ 提供多个方案让 AI 对比
✅ 要求 AI 解释每个方案的权衡
❌ 不要盲目采纳第一个建议
阶段三:工程优化(2-3 周)
构建缓存
增量更新
错误监控
AI 协作建议:
✅ 提出优化目标,让 AI 设计方案
✅ 和 AI 一起分析性能瓶颈
❌ 不要让 AI 代替你思考"为什么要优化"
关键原则:
AI 是加速器,不是替代品。
它可以让你的学习速度提升 3-5 倍,但前提是你已经有了一定的基础。
10.2 技术选型建议
// 根据需求选择技术栈(2026 年版)
const techStack = {
beginner: {
// 快速上手,专注内容
builder: 'Hexo',
hosting: 'Vercel',
theme: 'Next',
ai_usage: '配置问题咨询'
},
intermediate: {
// 平衡学习与效率
builder: '自研 + marked',
hosting: 'GitHub Pages',
features: ['标签', '归档', 'RSS'],
ai_usage: '代码实现 + 方案对比'
},
advanced: {
// 完全控制,深度定制
builder: '完整构建系统',
hosting: '多云协同',
features: ['插件系统', '评论', '搜索'],
ai_usage: '架构评审 + 性能优化'
}
};
看到 ai_usage 字段了吗?不同阶段,AI 的用法不同。
初学者:用 AI 查文档、问配置
进阶者:用 AI 写代码、比方案
高手:用 AI 做评审、提建议
你现在在哪个阶段?就用对应的 AI 用法。
10.3 避免的坑
❌ 我踩过的坑:
- 过度依赖 AI:一开始连
console.log()都让 AI 写,结果离开了 AI 就不会调试
- 改进:现在只在复杂场景用 AI,简单问题自己解决
- 不验证就使用:AI 给的第一个方案直接用,结果有 bug
- 改进:现在会要求 AI 给出测试用例,并且自己跑一遍
- 不记录对话:同样的问题问了三次 AI,每次都重新解释
- 改进:建立了知识库,效率提升 50%
- 不好意思承认用了 AI:觉得"这不算是我的作品"
- 改进:坦然面对,重点是我理解、我掌控、我创造
✅ 给你的建议:
从 MVP(最小可行产品)开始:先让系统跑起来,再慢慢优化
每个功能都要有文档记录:包括为什么这么设计、有哪些备选方案
参考优秀开源项目的设计:但要用自己的方式实现
至少要有基础的单元测试:AI 生成的代码也要测试
定期 review AI 生成的代码:确保没有"黑盒"
10.4 关于 AI 协作的真心话
我知道你在想什么:
"用了 AI,这还算是我的作品吗?"
我的回答:
如果架构是你设计的,算
如果每行代码你都理解,算
如果有问题你能修复,算
如果有人问你能讲清楚,算
反之:
如果只是复制粘贴,不算
如果离开 AI 就不会改,不算
如果被问到实现细节支支吾吾,不算
区别在哪里?
在于你是主导者还是搬运工。
我写这篇文章,就是想证明:
即使大部分代码是 AI 写的,只要方法得当,你依然可以学到很多,而且比从零手写学得更多、更快。
关键在于:
你是否真正理解了代码
你是否具备修改和优化的能力
你是否从中总结出了方法论
你是否能把这些经验复用到其他项目
如果答案是肯定的,那么:
用了 AI 又怎样?你依然是这个项目的创造者。
项目资源
扩展阅读
版权声明:本文为个人技术实践记录,遵循 CC BY-NC-SA 4.0 协议。欢迎分享,但需保留原文链接。
最后更新:2026年3月12日
作者:阳光
分类:技术实践 / 前端工程 / 个人项目