Vibe Coding 初体验:WordPress 主题开发
我的博客主题原先就是参考Medium.com进行搭建的,但是参考的是上一版Medium.com的样式。Medium.com已经改版很久,本周抽了些时间,尝试使用Workbuddy重新制作一份。
初版样式:

最终效果:

开发工具:Workbuddy+GLM 5.2模型,纯 AI 辅助(Vibe Coding),开发者通过自然语言描述需求,AI 生成全部代码并完成验证,只观看最终效果,不调整一行代码。
开发耗时:5天(大概每天20:00~22:00,每天花2小时左右), 从 v1.0.0 到 v1.9.0,共36个版本。总共10个小时,整体的效率是非常的高。
技术栈: 原生 PHP + WordPress 主题规范,CSS Variables + Grid/Flex,原生 JS(无 jQuery),无构建工具。

这是一次用 AI 辅助开发 WordPress 主题的完整记录,也是一份关于”Vibe Coding”实践的真实复盘。
开发历程概览
| 日期 | 版本范围 | 核心工作 |
| 8月3日 | v1.0.0 → v1.2.7 | 主题改造启动:阅读时间修复、三栏布局、字号调整、Footer 简化、Logo 替换、分类图标 |
| 8月4日 | v1.2.7 → v1.3.0 | 持续迭代:Tab 改造、卡片优化、右侧栏重构、标签聚合页、Logo AI 生成 |
| 8月5日 | v1.3.0 → v1.5.8 | 文章页深度改造:互动栏、分享弹窗、打赏功能、TOC 导航、评论美化、相关推荐 |
| 8月6日 | v1.5.8 → v1.7.5 | 系统化治理:代码审计、全局重命名、字体/颜色系统化、移动端优化 |
| 8月7日 | v1.7.5 → v1.9.0 | 精打细磨:样式统一、主色调更换、置顶样式、表格优化 |
五天累计 36 个版本,平均每天 7 个版本迭代。最高频的一天(8月5日)产出了 11 个版本。
开发过程中的问题及原因分析
将开发过程中遇到的典型问题按根因类型分为三大类:前期规划不足、技术细节盲区、迭代引入的回归。
第一类:前期规划不足(”一开始就该想清楚的”)
这类问题的共同特征是:如果在动手前多花十分钟想清楚,就能避免后续多轮返工。
侧边栏交互方案:三次改版
这是整个项目中最大的返工案例。
- 2.0:初版三栏布局,左侧栏用 hover 显隐小箭头来折叠
- 2.1:用户反馈”小箭头不是 Medium 现版的交互”,改为汉堡按钮 + fixed overlay 弹出层滑入
- 2.2:用户反馈”侧边栏非弹出层”,又改回内联 grid 列
为什么会出现?开发前没有充分理解 Medium 的布局模式。Medium 使用的是 column-drop 响应式模式——侧边栏是页面布局中的内联列,而非浮层。如果一开始就搜索确认了这一点,三次改版可以缩减为一次。
教训: 参考别人的设计时,不能只看”长什么样”,还要理解”交互模式是什么”。截图能看到视觉,但交互逻辑需要实际体验或查阅资料确认。
字号连续两轮加大
- 2.3:用户反馈”字体有点小”,参考 biaodianfu.com 做了第一轮加大
- 2.4:用户反馈”字体还是太小”,参考 Medium.com 实际字号做了第二轮大幅提升
为什么会出现? 第一轮参考的是biaodianfu.com,而非目标参考站 Medium.com 本身。中文和英文的字号需求不同,且第一轮调整幅度过于保守。直到第二轮直接参考 Medium 的实际尺度(正文 20px+、卡片标题 22-24px),才到位。
教训: 参考对象要选对。既然主题是仿 Medium,就应该直接量 Medium 的字号,而不是绕道参考另一个站点。另外,字号调整不要”挤牙膏”——要么一步到位,要么先做一个预览让用户确认。
布局方案选错:float 还是 flexbox
- 4.0:文章页互动栏用 float: right + margin-right: -56px
- 4.1:发现 float 导致文本环绕浮动元素,排版畸形,改为 flexbox
为什么会出现? float 是传统布局手段,但在需要元素并排且不干扰文本流的场景下,flexbox 才是正确选择。AI 在初次实现时选了”能用”的方案而非”最合适”的方案。
教训:布局方案的选择应该在实现前就确定好。对于并排布局,2024 年以后的项目应该直接用 flexbox 或 grid,float 只用于文字环绕图片等传统场景。
全局命名不一致
项目从始至终使用了 Medium_Clone / medium_clone / medium-clone 三种前缀混用,直到 v1.6.2 才统一重命名为 WP_Medium / wp_medium / wp-medium,涉及 18 个文件、180+ 处替换。
为什么会出现?项目初期的命名前缀来源于主题原始名称(Medium Clone),但随着项目定位明确为 wp-medium,旧前缀没有同步更新。AI 在每次新增代码时都沿用了旧前缀,导致债务越积越深。
教训:项目命名规范应该在第一天就确定,并记录在项目记忆文件中。一旦确定,所有新代码都必须遵守。如果需要改名,越早越好——越晚改,涉及的面越广。
版本号硬编码
每次版本升级都需要手动修改 functions.php 中的 CSS/JS enqueue 版本号字符串。直到代码审计时才发现,改为 wp_get_theme()->get(‘Version’) 动态获取后,再也不用手动改了。
为什么会出现? 初期为图方便直接硬编码。AI 在每次迭代时都忠实地更新了版本号字符串,但没有人想到”这应该自动化”。
教训: 重复性的手动操作是bug的温床。如果一个值在多个地方重复出现且需要同步更新,它就应该被提取为变量或动态获取。
硬编码颜色和字体泛滥
代码审计发现 22 处硬编码 font-size: Xpx 和 25+ 处硬编码颜色值,散落在各处 CSS 规则中。虽然项目一开始就定义了 CSS 变量系统,但开发过程中 AI 经常直接写具体数值而非引用变量。
为什么会出现? AI 在实现具体样式时,”就近写值”比”先查变量名再引用”更直接。这种便利性在当下是高效的,但长期来看破坏了系统的可维护性——改一个主色调需要全局搜索替换,而非改一个变量。
教训: 设计系统(Design System)的价值在于”单一数据源”。变量定义了就必须使用,新代码review时要检查是否引用了变量而非硬编码。这在 Vibe Coding 中尤为重要——因为 AI 不会自觉使用你的变量系统,除非你在指令中明确要求。
第二类:技术细节盲区(”不知道自己不知道的”)
这类问题的共同特征是:涉及特定技术栈的边界行为或兼容性问题,不是逻辑错误,而是知识盲区。
str_word_count 对中文无效
原版 medium_clone_reading_time() 用 str_word_count 计算字数来估算阅读时间,但这个函数对中文完全无效——它按空格分词,中文没有空格。
为什么会出现? 这是 PHP 函数的 i18n 盲区。str_word_count 设计于英文语境,对 CJK 字符天然不友好。修复方案是分别处理:CJK 按字符数计(~400字/分),英文按词数计(~200词/分)。
教训: 在中文项目中使用 PHP 字符串函数时,必须验证其 CJK 兼容性。strlen、substr、str_word_count 都有这个问题,对应的替代方案是 mb_strlen、mb_substr、以及自定义的 CJK 字符计数。
substr 中文截断乱码
评论头像取用户名首字母时,用 substr(get_comment_author(), 0, 1) 截取第一个字符,中文用户名直接乱码——因为 substr 按字节截取,UTF-8 编码下每个中文字符占 3 个字节。
为什么会出现? 和上一个问题同源:PHP 原生字符串函数的字节级操作与 UTF-8 多字节编码不兼容。修复方案是 mb_substr($author_name, 0, 1, ‘UTF-8’)。
教训: 同上。PHP 项目处理中文时,mb_* 系列函数应该是默认选择,而非备选。
WordPress .sticky 类的隐藏行为
自定义置顶文章样式时,反复出现背景色残留问题。根因是 WordPress 的 post_class() 函数会自动给置顶文章添加 .sticky CSS 类,而主题 CSS 中已有一条 .sticky 规则设置了背景色,与自定义的 .is-featured 类冲突。
为什么会出现? 不了解 WordPress 内置的 CSS 类生成机制。post_class() 会根据文章状态自动添加多种类名(.sticky、.category-xxx、.tag-xxx 等),如果主题 CSS 中有同名规则,就会产生冲突。
教训: 开发 WordPress 主题前,应该先了解 post_class()、body_class() 等核心函数的输出内容。避免使用与 WordPress 内置类名冲突的自定义类名。
current_time(‘timestamp’) 已废弃
代码审计发现 4 个文件使用了 current_time(‘timestamp’),这在 PHP 8.1+ 会产生废弃警告。
为什么会出现? 这是 WordPress API 的版本演进问题。current_time(‘timestamp’) 在早期 WP 版本中是标准用法,但已废弃,应直接用 time()。
教训: WordPress API 也有生命周期。使用任何 API 前最好查阅最新文档,确认是否已废弃。定期运行代码审计可以批量发现这类问题。
DOMDocument 破坏 HTML 结构
wp_medium_add_heading_ids() 函数用 DOMDocument 解析文章 HTML 来给标题添加 anchor ID,但 saveHTML() 会破坏段落结构——当段落以 <strong> 或 <a> 开头时,后续文字被错误拆分成新段落。
为什么会出现? DOMDocument 的 saveHTML() 方法会”规范化”HTML,但它的规范化逻辑与 WordPress the_content 过滤器输出的 HTML 不完全兼容。特别是内联元素在段落开头的场景,saveHTML() 会补全闭合标签,导致段落被拆分。
教训: 使用 DOM 解析库操作 HTML 时要格外小心。如果只需要做简单的属性注入(如给标题加 ID),正则替换往往更安全——它不会改变 HTML 结构,只做精准替换。
CSS 优先级覆盖问题
搜索框点击后出现绿色 outline 焦点框,不够美观。根因是全局 :focus-visible 规则的 outline 优先级高于搜索框自身的 outline: none。
为什么会出现? CSS 优先级是个经典难题。全局规则和组件级规则之间的优先级关系,在代码量增大后变得越来越难追踪。
教训: 全局 CSS 规则(尤其是 :focus-visible、* 选择器等)要谨慎使用。对于需要例外样式的组件,确保组件级选择器有足够高的优先级(如使用更具体的选择器或 !important 作为最后手段)。
第三类:迭代引入的回归(”改着改着就坏了”)
这类问题的共同特征是:每一轮迭代本身是正确的,但在修改过程中意外破坏了既有功能。
HTML 结构嵌套错误导致排版崩溃
v1.5.7 版本中,文章页整体排版突然乱了。根因是上一轮添加打赏弹窗时,HTML 结构嵌套出现错误——.post-body-content(正文容器)被错误地放在了 flex 容器外面,导致 flex 布局完全失效。
为什么会出现? AI 在添加新 HTML 块(打赏弹窗)时,不小心提前闭合了外层 div,导致后续内容都跑到了容器外面。这是”在复杂 HTML 结构中插入新代码”时的典型风险。
教训: 在复杂的嵌套 HTML 结构中做修改时,修改前后都应该验证结构完整性。一个简单的检查方法:数 <div> 和 </div> 的数量是否一致,或者用 PHP 的 php -l 配合浏览器的开发者工具检查 DOM 树。
CSS 选择器误伤非目标元素
v1.6.5 中为了让文章页分类标签与左侧栏对齐,给 .home-layout–single .single-post-container 添加了 padding-top。但这个选择器同时匹配到了 .single-post-container–content(正文容器),导致正文区域多了一层不必要的内边距。
为什么会出现? CSS 选择器 .single-post-container 同时匹配 .single-post-container 和 .single-post-container–content(因为后者也包含前者的类名)。这是 BEM 命名规范的经典陷阱——.single-post-container 不是 .single-post-container–content 的”父级”,它们是两个独立的类名。
教训: CSS 类名使用 BEM 规范时要注意:.block 和 .block–modifier 是两个独立的类,选择器 .block 会同时匹配两者。如果只想匹配前者,需要用 :not(.block–modifier) 排除,或者使用更精确的类名。
评论计数为零仍显示绿点
互动栏评论按钮的计数徽章,在评论数为 0 时仍然显示为一个绿色圆点。根因是 PHP 三目运算符在评论数为 0 时返回空字符串,但 <span> 元素本身仍然存在于 DOM 中,CSS 给它渲染出了一个空内容的圆形。
为什么会出现? 只处理了”有内容时显示什么”,没有处理”无内容时元素是否应该存在”。空字符串不等于”不存在”——DOM 节点还在,CSS 还在生效。
教训: 边界条件不只是”值是多少”,还包括”元素是否存在”。当值为零/空时,最好的做法是用 if 条件判断决定是否渲染整个元素,而非渲染一个空内容的元素。
主色调选择反复
- 8.0 之前:使用 Medium 绿 #1a8917
- 8.1:改为湖蓝 #1cd4b9
- 8.2:#1cd4b9 饱和度过高、刺眼,降为 #2a9d8f
为什么会出现? 色彩在屏幕上的实际效果很难通过色值预判。#1cd4b9 在色板上看起来不错,但在大面积使用(按钮、链接、高亮)时过于刺眼。这是视觉设计与代码实现之间的固有差距。
教训: 色彩选择应该在真实页面中验证,而非仅看色板。可以先做一个测试页面,把候选色应用到所有需要主色的元素上,截图对比后再做决定。好在项目使用了 CSS 变量系统,主色调更换只需要改 :root 中的几个变量值——这正是设计系统的价值所在。
问题分布统计
| 问题类型 | 数量 | 占比 | 典型案例 |
| 前期规划不足 | 6 | 37.5% | 侧边栏三次改版、命名不一致、硬编码泛滥 |
| 技术细节盲区 | 6 | 37.5% | 中文截断乱码、WP sticky类、DOMDocument破坏HTML |
| 迭代引入回归 | 4 | 25% | HTML结构崩溃、CSS选择器误伤、零值绿点 |
关键发现: 前期规划不足和技术细节盲区各占 37.5%,是最大的两类问题来源。迭代回归虽然只占 25%,但单次影响最大——比如 HTML 结构崩溃会导致整个页面排版失效。
项目推进经验总结
参考对象要”看懂”而非”看像”
侧边栏三次改版的教训。仿站开发中,截图只能传递视觉信息,交互模式和布局逻辑需要实际体验或查阅资料来确认。Vibe Coding 时,应该先让 AI 搜索确认参考对象的设计模式(如 Medium 使用 column-drop 响应式模式),再开始编码。
实践建议: 开发前先花 10 分钟让 AI 做”参考对象分析“——它的布局模式是什么?响应式策略是什么?核心交互组件有哪些?这 10 分钟能省掉后续几小时的返工。
设计系统要”第一天就建好”
硬编码泛滥和命名不一致的教训。CSS 变量系统、命名规范、版本号管理机制,这些”基础设施”应该在项目第一天就建立,并写入项目记忆文件。Vibe Coding 中,AI 不会自觉遵守你的规范——除非你在每次指令中提醒它”使用 CSS 变量而非硬编码值”。
实践建议: 在项目记忆文件(MEMORY.md)中明确记录:
- 命名前缀规范(如 wp_medium_ / wp-medium)
- CSS 变量清单(颜色、字号、间距)
- 版本号管理方式(动态获取 vs 手动维护)
- 每次让 AI 写新代码时,提醒它引用已有变量
边界条件要想”三层”
评论计数零值绿点的教训。边界条件不只是”值等于零时怎么办”,还要想:
- 值层: 零值、空字符串、null 的处理
- 元素层: 值为零时,DOM 元素是否应该存在
- 样式层: 元素存在但内容为空时,CSS 是否会产生副作用(如空内容的圆点)
实践建议: 处理动态数据时,问自己三个问题:值为零怎么办?元素该不该渲染?渲染了会不会有副作用?
迭代修改要”验证结构”
HTML 结构崩溃和 CSS 选择器误伤的教训。Vibe Coding 的迭代速度很快,但每次修改都可能引入回归。特别是在复杂的 HTML 嵌套结构中插入新代码时,很容易破坏标签闭合关系。
实践建议: 每次修改后执行三个验证:
- PHP 语法验证: php -l 检查语法
- JS 语法验证: node –check 检查语法
- CSS 大括号配对: 检查 { 和 } 数量是否一致
- HTML 结构验证: 检查 <div> 和 </div> 数量是否一致
这套验证流程在项目中后期已经形成习惯,有效减少了结构错误的发生。
技术选型要”一步到位”
float vs flexbox、硬编码版本号的教训。布局方案、API 选择、代码组织方式,这些”架构级”决策应该在实现前就确定好。选错方案后返工的成本,远高于多花几分钟做技术选型的成本。
实践建议: 对于核心布局,直接使用 flexbox/grid;对于 PHP 字符串操作,默认使用 mb_* 系列;对于版本号管理,用动态获取而非硬编码。这些”默认选择”应该写入项目记忆,让 AI 在每次实现时都遵循。
代码审计是”必要的补救”
v1.6.2 一次性修复 18 项问题的教训。
Vibe Coding 模式下,开发速度优先于代码质量,技术债务会快速积累。定期进行代码审计是必要的补救措施——一次性发现并修复所有遗留问题,比零散修修补补更高效。
实践建议: 每完成一个里程碑(如 5-10 个版本迭代),进行一次完整的代码审计,检查:
- 是否有硬编码值应该替换为变量
- 是否有废弃 API 调用
- 是否有命名不一致
- 是否有未使用的死代码
- 是否有安全隐患(如未转义的输出)
让 AI 记住你的偏好
Vibe Coding 的核心优势是”对话式开发”,但如果每次对话都要重新说明你的偏好,效率会大打折扣。项目记忆文件(MEMORY.md / 每日工作日志)是让 AI “记住”你的关键工具。
实践建议: 把以下内容写入项目记忆:
- 你的设计偏好(如”参考com 的极简风格”)
- 你的技术约束(如”使用 mb_* 函数处理中文”)
- 你的验证流程(如”每次修改后执行 php -l 和 node –check”)
- 你的命名规范(如”所有前缀用 wp_medium_”)
这样 AI 在每次新会话中都能延续你的工作方式,而不需要重新学习。
Vibe Coding 的优势与代价
优势:
- 开发速度极快:5天36个版本,涵盖布局/交互/样式/审计全流程
- 降低实现门槛:不需要精通 PHP/CSS/JS 的每个细节,描述需求即可
- 快速试错:不确定的效果可以先让 AI 生成,不满意再调整
- 自动验证:AI 可以在生成代码后自动执行语法检查和配对验证
代价:
- 返工率高:前期规划不足导致多次改版(如侧边栏三次重做)
- 技术债务积累快:硬编码、命名不一致等问题在高速迭代中快速堆积
- 需要人工把关:AI 不会自觉使用设计系统,需要人工持续提醒
- 结构风险:高频修改 HTML 结构时容易引入回归(如排版崩溃)
核心结论
Vibe Coding 不是”零基础也能开发”的银弹,而是”有经验的人用 AI 加速开发”的工具。它的效率优势是真实的,但前提是:
- 你知道要做什么(前期规划)
- 你知道怎么验证(结构检查 + 语法验证)
- 你知道何时该停下来还债(定期代码审计)
如果只是无脑地”说一句改一句”,迭代速度会被返工抵消,最终效率可能还不如传统开发。但如果能在速度和质量之间找到平衡——用 AI 的速度生成代码,用经验把关方向和质量——Vibe Coding 确实能带来数量级的效率提升。
写在最后
这次 WordPress 主题开发是 Vibe Coding 的一次完整实践。从 v1.0.0 到 v1.9.0,36 个版本迭代,15+ 个典型问题,3 大类根因——这些数字本身就是最好的教材。
Vibe Coding 的”Vibe”(感觉/氛围),不是盲目跟着感觉走,而是在快速迭代中保持对方向的敏感、对质量的警觉。就像开车一样——速度快不代表要蒙着眼睛开。恰恰相反,速度越快,越需要看清路况。
希望这篇复盘能为你下一次的 Vibe Coding 实践提供一些参考。记住:AI 是油门,你才是方向盘。





