凌晨 2 点。Leverage OJ 前端已经愉快地服务页面好几个小时了,然后某些东西导致它崩溃。快速重启后,每个路由都返回默认的 Nuxt 欢迎页面:
通过将
<NuxtWelcome />替换为你自己的代码来移除这个欢迎页面...
代码没有改变。app/app.vue 完好无损。那发生了什么?
背景设置
项目使用带有 Nuxt 4 兼容标志的 Nuxt 3.21.1:
大约 3 分钟
凌晨 2 点。Leverage OJ 前端已经愉快地服务页面好几个小时了,然后某些东西导致它崩溃。快速重启后,每个路由都返回默认的 Nuxt 欢迎页面:
通过将
<NuxtWelcome />替换为你自己的代码来移除这个欢迎页面...
代码没有改变。app/app.vue 完好无损。那发生了什么?
项目使用带有 Nuxt 4 兼容标志的 Nuxt 3.21.1:
Leverage OJ 的后端重写已经在进行中——干净的架构、正经的 migration、真实的认证体系——但前端还是原来那套:Vue 2 的应用,API 调用散落各处,没有类型安全,构建流水线需要点运气才能跑起来。既然要修地基,屋顶也一起修了吧。
这篇文章记录前端重写的全过程:为什么做、选了什么技术、哪些架构决策经受住了考验,以及 Playwright 测试实际跑起来之后才暴露的那几个 bug。
旧前端积累了快速迭代项目的常见问题:
axios 调用直接写在组件里,有的重复,有的错误处理逻辑微妙不同。给每个请求加认证头需要改动每一处。any。TypeScript 只是名义上存在。有些项目悄悄地积累债务。Leverage OJ 不是其中之一——它大声地积累,表现为比赛中途冻结的排名系统、在 PM2 集群下崩溃的认证系统、每次请求都扫描整个提交表的排行榜,以及离全量凭证泄露只差一个配置泄漏的密码哈希方案。
这是完整重写的故事:我们替换了什么、为什么,以及在这个过程中学到了什么。
原版 Leverage OJ 是一个在真实约束下快速推进的项目。开发者是深思熟虑的——你可以从架构决策中看出来。但六年的功能添加、午夜修复和"在我机器上能跑"的补丁已经堆成了一座摇摇欲坠的塔。