从零搭建静态博客:现代前端工程化实践与思考

记录从零开始搭建个人静态博客的技术选型、架构设计和工程化思考,探索基础学习能力与 AI 工具如何协同促进快速成长。

Mingshuo_S
Mingshuo_S
编程菜鸟这一块

从零搭建静态博客:现代前端工程化实践与思考

从零搭建静态博客:现代前端工程化实践与思考

最好的学习方式是创造,而创造的最佳起点是构建一个属于自己的数字花园。在这个 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[选择纯前端]

决策依据

  1. 内容性质:博客以文字为主,交互需求简单

  2. 性能要求:静态文件可被CDN缓存,加载极快

  3. 成本考量:GitHub Pages 提供免费托管

  4. 维护成本:无需服务器运维,专注内容创作

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();

    }

  }

}

构建流程

  1. 清理阶段:删除旧的构建文件

  2. 读取阶段:加载配置和内容

  3. 转换阶段:Markdown → HTML,模板渲染

  4. 生成阶段:输出静态文件

  5. 优化阶段:压缩、合并、添加哈希

这个架构怎么来的?

我给 AI 的描述是:

"我想要一个类似工厂流水线的构建系统,每个步骤独立可测,失败了能优雅处理,还能方便地加新功能。"

AI 给了我第一版代码——用的是简单的函数调用链。

我让它改了两次:

  1. "改成类的设计,这样状态管理更方便"

  2. "加上 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 技术层面的提升

通过这个项目,我学到了什么?

  1. Node.js 文件系统操作:深入理解了异步文件处理

   - 虽然大部分代码是 AI 写的,但我 review 了每一行

   - 知道了 fs.readFile()fs.readFileSync() 的区别

   - 学会了用 fs-extra 增强错误处理

  1. 构建工具原理:理解了 Webpack、Vite 等工具的基本思想

   - 通过自己实现一个简单的构建系统

   - 明白了"打包"、"转换"、"优化"的本质

   - AI 帮我实现了细节,但我理解了整体

  1. 模块化设计:学会了如何设计可维护的代码结构

   - 从 AI 给的第一版"面条代码"开始

   - 我要求它重构为类的设计

   - 逐步演进出现在的 pipeline 架构

  1. 性能优化:掌握了前端性能优化的多种策略

   - AI 建议的缓存机制

   - 我提出的增量构建想法

   - 共同实现的懒加载方案

  1. AI 协作能力:这可能是最重要的收获

   - 学会了如何向 AI 清晰地描述问题

   - 学会了如何验证 AI 给出的方案

   - 学会了如何在 AI 的基础上继续优化

说实话:如果这个项目的代码 100% 是我自己写的,我可能学得更深。

但我也敢说:现在这种"20% 设计 + 30% Review + 50% AI 实现"的模式,让我在相同时间内学到了更多。

因为我把省下来的时间用来:

  • 深入理解架构设计的权衡

  • 思考如何把这个模式复用到其他项目

  • 写文章分享经验(比如你现在看的这篇)

这才是 AI 时代的正确学习方式。

9.2 工程思维的形成

  1. 迭代开发:从简单到复杂,逐步添加功能

   - 第一版只能解析 Markdown

   - 第二版加了模板变量替换

   - 第三版支持条件渲染

   - 第四版实现路径自动转换

   AI 的作用:快速实现每个版本的基础功能

   我的作用:决定迭代方向,把控代码质量

  1. 错误处理:学会了防御性编程和错误边界处理

   - AI 最初给的代码没有错误处理

   - 我让它加上了 try-catch

   - 后来又要求区分致命错误和警告

   - 最后实现了优雅的降级方案

  1. 文档意识:代码注释、README、技术文档的撰写

   - AI 生成的代码注释很简陋

   - 我重新写了所有关键函数的注释

   - 补充了使用示例和注意事项

   - 这个过程让我更理解代码本身

  1. 版本控制:合理的 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 避免的坑

❌ 我踩过的坑

  1. 过度依赖 AI:一开始连console.log()都让 AI 写,结果离开了 AI 就不会调试

   - 改进:现在只在复杂场景用 AI,简单问题自己解决

  1. 不验证就使用:AI 给的第一个方案直接用,结果有 bug

   - 改进:现在会要求 AI 给出测试用例,并且自己跑一遍

  1. 不记录对话:同样的问题问了三次 AI,每次都重新解释

   - 改进:建立了知识库,效率提升 50%

  1. 不好意思承认用了 AI:觉得"这不算是我的作品"

   - 改进:坦然面对,重点是我理解、我掌控、我创造

✅ 给你的建议

  1. 从 MVP(最小可行产品)开始:先让系统跑起来,再慢慢优化

  2. 每个功能都要有文档记录:包括为什么这么设计、有哪些备选方案

  3. 参考优秀开源项目的设计:但要用自己的方式实现

  4. 至少要有基础的单元测试:AI 生成的代码也要测试

  5. 定期 review AI 生成的代码:确保没有"黑盒"

10.4 关于 AI 协作的真心话

我知道你在想什么

"用了 AI,这还算是我的作品吗?"

我的回答

  • 如果架构是你设计的,

  • 如果每行代码你都理解,

  • 如果有问题你能修复,

  • 如果有人问你能讲清楚,

反之

  • 如果只是复制粘贴,不算

  • 如果离开 AI 就不会改,不算

  • 如果被问到实现细节支支吾吾,不算

区别在哪里?

在于你是主导者还是搬运工

我写这篇文章,就是想证明:

即使大部分代码是 AI 写的,只要方法得当,你依然可以学到很多,而且比从零手写学得更多、更快。

关键在于:

  • 你是否真正理解了代码

  • 你是否具备修改和优化的能力

  • 你是否从中总结出了方法论

  • 你是否能把这些经验复用到其他项目

如果答案是肯定的,那么:

用了 AI 又怎样?你依然是这个项目的创造者。


项目资源

扩展阅读

  1. https://www.netlify.com/blog/2020/04/14/what-is-a-static-site-generator-and-3-ways-to-find-the-best-one/

  2. https://frontendmasters.com/books/front-end-handbook/2019/4-tools/

  3. http://aosabook.org/en/


版权声明:本文为个人技术实践记录,遵循 CC BY-NC-SA 4.0 协议。欢迎分享,但需保留原文链接。

最后更新:2026年3月12日  

作者:阳光

分类:技术实践 / 前端工程 / 个人项目