一个运行了 6 年的 Laravel 博客,在 AI Coding 时代完成了一次完整迁移。
项目地址:https://github.com/HubQin/qinblog-go
在线地址:https://blog.ishare.cool/(现在跑的已经是 Go 版了)
背景
这个博客是 2020 年用 Laravel 6 搭的,功能还算完整:文章、分类标签、嵌套评论、用户认证、GitHub 登录、站内通知、全文搜索、后台管理。
当年和现在的技术栈对比如下:
┌─────────────┬───────────────────┬───────────────────────────┐
│ 组件 │ Laravel 版 │ Go 重构版 │
├─────────────┼───────────────────┼───────────────────────────┤
│ 语言 │ PHP 7.3 │ Go 1.25 │
│ 框架 │ Laravel 6 │ Gin │
│ ORM │ Eloquent │ GORM │
│ 模板 │ Blade │ html/template │
│ 前端 │ Vue 2 + Mix │ Vue 3 + Vite │
│ 搜索 │ TNTSearch+jieba │ bleve CJK Analyzer │
│ 后台 │ laravel-admin │ 自建 (is_admin) │
│ 队列 │ Redis Queue │ goroutine (内嵌) │
│ 调度 │ Supervisor │ robfig/cron (内嵌) │
│ 部署 │ PHP-FPM 容器 │ 单二进制 + Docker │
│ 配置 │ config/site.php │ settings 数据库表 │
└─────────────┴───────────────────┴───────────────────────────┘
为什么选择重构
其实博客一直运行得很好,Laravel 6 稳定跑了 6 年,文章、评论、后台都没出过问题,功能也够用。
但用久了,心里越来越有个感觉:
对于一个个人博客来说,Laravel 还是太重了。
Laravel 是个很优秀的框架,ORM、Service Container、Middleware、Event、Queue、生态那是真的丰富,大项目里这些东西非常值钱。
可博客本身其实就这么几样:展示文章、管理内容、提供搜索、少量后台功能。一个简单的网站,却跑在一整套完整框架上面。
结果就是:启动慢一点,链路长一点;改个代码还得惦记着 PHP 环境、Composer 依赖、Laravel 版本;部署也绕不开 PHP-FPM、Nginx 这些东西。倒也不是 Laravel 有什么问题,只是它解决的问题规模,已经远远超过了博客本身的需求。
为什么选择 Go
原因很直接:轻、快、简单。
Laravel: Go:
─────── ────
Nginx Nginx
↓ ↓
PHP-FPM Go Binary
↓ ↓
Laravel Framework Handler
↓ ↓
Container ↓
↓ Response
Middleware
↓
Controller
↓
Response
不需要 PHP-FPM,不需要 Composer,编译成一个二进制就能跑。
AI 降低了重构成本
以前一个 6 年的 Laravel 项目,想迁移到 Go,最麻烦的不是写代码,而是读旧代码、搞懂业务、搬迁功能、验证结果这一整条链路。投入太大了,结论往往就是「不值得折腾」。
这次刚好赶上 Qoder 给了大量免费额度,AI 帮忙分析旧项目、生成迁移代码、补测试、快速迭代。成本一下子降下来了。
所以这次重构,本质上不是因为 Laravel 不能用。而是:当 AI 降低了重构成本,一个更轻、更适合自己的技术方案,值得重新选择。
第一次尝试:一句简单的 Prompt
最开始给 AI 的就一句话:
将这个 Laravel 写的 blog 重构到 Golang,
使用 Gin 框架,golang template 渲染;看前端如何结合 Vue。
这显然不是完整需求——数据库要不要保持?laravel-admin 怎么办?Observer 怎么替代?搜索系统呢?一堆东西没明确。所以没有让 AI 直接动手写。
使用 Spec 模式梳理需求
用的是 Qoder 的 Spec 模式,类似传统需求分析——先让 AI 把 Laravel 源码通读一遍(Model、Controller、Migration、Observer、Blade 模板、Vue 页面),再确认范围。
输出结果如下:
┌──────────────────────────────────────────────────────────────┐
│ Spec 需求分析输出 │
├──────────────────────────────────────────────────────────────┤
│ ✅ 保持的功能:文章 CRUD + 多标签 / 多级嵌套评论 + 通知 / │
│ 用户注册登录 + GitHub OAuth / 全文搜索 (中文分词) / │
│ 年月归档 + 分类 + 标签 + 专题 / MySQL 11 张表 零数据迁移 / │
│ 后台管理 (仪表盘 + 9 组 CRUD) │
│ │
│ 🔄 替换:TNTSearch+jieba → bleve CJK / Redis Queue → goroutine│
│ Supervisor → robfig/cron / config/site.php → settings│
│ │
│ ✂️ 砍掉:laravel-admin RBAC → users.is_admin 单一字段 │
└──────────────────────────────────────────────────────────────┘
至此,核心原则就一条:保持业务一致,不做重新设计——功能一致、表结构不变、行为逐一对等。
Goal 模式开始执行
后端:Gin + GORM 模板:html/template 搜索:bleve
前端:服务端渲染 + Vue3/Vite 组件化 后台:自建替代 laravel-admin
到这里,AI 做的已经不是「帮我写个博客」了,而是「完成一次确定范围的软件迁移」。
迁移过程
整个过程的时间线:
时间线 (7h13min)
═══════════════════════════════════════════════════════════
00:00 骨架搭建 go mod init / 目录 / config / database / models / render
02:00 前台功能 posts / comments / auth / tags / topics / notifications
04:00 后台管理 仪表盘 + 9 组 CRUD + 站点设置
05:30 前端迁移 Blade → Go template / Vue2 → Vue3 / Mix → Vite
06:30 验证 单元测试 + 端到端 (12 张截图)
07:13 完成
以上,主要模块的迁移记录如下。
1. 后端迁移
Laravel 到 Go 的对应关系,基本是一层对一层:
┌───────────────┬──────────────────┬───────────────────────────┐
│ 层 │ Laravel │ Go 重构版 │
├───────────────┼──────────────────┼───────────────────────────┤
│ 路由 │ routes/web.php │ internal/router │
│ 控制器 │ Controller │ internal/handlers/web │
│ 模型 │ Eloquent Model │ internal/models │
│ 数据库 │ Migration │ GORM AutoMigrate │
│ 业务逻辑 │ Service/Observer│ internal/services │
│ 模板 │ Blade │ html/template │
│ 中间件 │ Middleware │ internal/middleware │
│ 验证请求 │ FormRequest │ handler 内校验 │
│ 工具函数 │ helpers.php │ internal/support │
└───────────────┴──────────────────┴───────────────────────────┘
数据库结构保持不变,继续用原 MySQL 表——用户、文章、评论全都不用迁移,零数据转换。
2. 前端迁移
Blade Go template
══════════════════════════════ ═══════════════════════
@extends('layouts.app') {{template "layout" .}}
@section('content') {{block "content" .}}
@include('partials.*') {{template "partials/*" .}}
@foreach($posts as $p) {{range .Posts}}
Vue 2: SimpleMDE/multiselect → Vue 3: EasyMDE/@vueform/multiselect
服务端渲染为主,Vue 组件只做增强。博客这种内容型网站,没必要搞成 SPA。
3. 搜索迁移
原:保存 → PostObserver → TNTSearch(jieba) → MySQL 索引 → 回 DB 查
新:保存 → Service Layer → bleve(CJK) → 索引文件 → 回 DB 查
4. 后台迁移
后台是迁移里工作量最大的一块。原来用的是 laravel-admin,admin_users 表、RBAC、菜单、操作日志一整套,上手确实容易,但个人博客真不需要这些。最后简化为一个 users.is_admin 字段加中间件拦截,9 组 CRUD 手写:文章、评论(批量审核)、分类、标签、专题、栏目、友链、用户、站点设置。
遇到的几个坑
1. bcrypt 密码兼容
报错:所有老用户都登不进去。
原因:Laravel 的 bcrypt 哈希用了 $2y$ 前缀,Go 的 x/crypto/bcrypt 只认 $2a$,就差一个字符。
解决:校验前把 $2y$ 替换为 $2a$ 即可。这个问题不读旧代码根本不会想到,很有意思。
2. Laravel Observer 隐藏逻辑
Laravel 保存一篇文章会悄悄触发一堆东西:
Laravel 隐式 (框架自动触发) Go 显式 (Service 手动调用)
══════════════════════════════════════ ═══════════════════════════
保存文章 → PostObserver::saved() 保存 → services.Post.Save()
├─ tags.post_count += 1 ├─ db.Save(&post)
├─ 更新全文索引 ├─ UpdateTagCount()
└─ 清理侧边栏缓存 ├─ Search.IndexPost()
└─ Sidebar.ClearCache()
删除评论 → CommentObserver::deleted() 删除 → services.Comment.Delete()
├─ posts.comment_count -= 1 ├─ db.Delete(&comment)
└─ 清理通知计数 └─ UpdateCommentCount()
副作用全藏在框架机制里 所有副作用显式写在 Service 里
迁移到 Go 后改成 Service 层显式调用,代码多了几行,但逻辑一眼就能看清,以后排查不用再猜了。
AI Coding 中最重要的一点
AI 不是替代开发,分工很明确:人负责定义目标、设计约束、判断取舍、验证结果;AI 负责读旧代码、生成迁移代码、辅助测试。
完整流程:需求定义 → Spec 梳理(AI 读 + 人确认)→ Goal 执行(AI 逐模块生成,循环修正)→ 验证收尾(单测 + 截图 + DEVELOPMENT.md)。
全程无人值守:AI 自己跑了一整夜
Spec 定好、Goal 启动之后,我基本上没再管过:
传统重构: 人 ████████████████████████████████ 100%
本次: 人 ███░░░░░░░░░░░░░░░░░░░░░░░░░███ 15%
AI ████████████████████████████ 85%
中间那些坑——bcrypt 兼容、Observer 隐藏逻辑、路由冲突、模板差异、搜索索引重建——AI 全自己处理了。我做的事情真的只有三件:凌晨 00:06 启动 Goal,中间放心睡了几个小时,早上起来一看:跑起来了。
当然,有个前提:这个博客的业务逻辑比较直接,边界很清晰,1:1 复刻让迁移范围完全确定。如果是多租户、复杂审批流那种系统,人的参与度肯定会高很多,验收也没那么容易。但对这类小项目,人确实可以「放手」。
这大概就是「AI 改变软件工程」最直接的体现:不是省了多少时间,而是人可以完全脱离执行层了。
最终结果
7 小时 13 分钟,一个人 + AI,完成了一次完整迁移。
交付如下:Go 博客完整运行(Gin + GORM / Vue3 + Vite / html/template)、自建后台 9 组 CRUD、bleve CJK 全文搜索、Docker 三阶段部署、单元测试、12 张端到端验证截图、DEVELOPMENT.md 交接文档、bcrypt $2y$ 兼容、内嵌 cron。
成本对比 手工 AI 辅助
═══════════════════════════════════════════
时间 2-4 周 7h13min
理解旧代码 几天 AI 读
写代码 1-2 周 对话式生成
调试 1 周 即时修复
AI 成本 $0 $27.26 (实付 $0)
最后,贴一下本次折腾的成果:https://blog.ishare.cool/,现在跑的已经是 Go 版了。
总结
这次最大的收获不是「AI 帮我写了多少代码」,而是发现:以前很多项目不是做不了,只是不值得投入。
以前: 想重构 → 评估 2-4 周 + 风险 → 不值得,继续跑吧
现在: 想重构 → 评估 7 小时 + $0 → 今晚就干
AI 降的是工程的启动成本。一个拖了 6 年的重构,一个晚上就搞完了。
未来的开发也许不是写更多代码,而是 让更多以前不敢开始的工程重新变得可行。
评论 (1)
强大