CASE STUDY / CONTENT PLATFORM

Linze.pro

当前项目

从 Vue 博客到 Next.js 双语内容平台

在保留 Go/chi 内容 API 与既有文章模型的前提下,使用 Next.js App Router 重建公开前端,补齐 Markdown 发布、双语回退、SEO、文章互动与后台内容管理链路。

01 / MIGRATION BRIEF

为什么要重构博客前端

旧 Vue 前端的组件结构和渲染边界不适合继续扩展,文章展示、语言切换、SEO 与互动逻辑也逐渐耦合。重构目标不是把 Vue 文件逐个翻译成 React,而是在保留 Go 后端和内容数据的前提下,重新建立从 Markdown 编辑、版本保存到公开阅读的完整内容链路。

  • 保留 Go 内容 API 与既有文章数据,渐进式替换公开前端
  • 让 Markdown Front-matter 成为可校验、可版本化的内容入口
  • 用独立的语言版本与明确的回退状态支持中英双语
  • 把 SEO、阅读体验、互动和可观测性纳入同一条交付链路

02 / CONTENT LIFECYCLE

一篇文章如何从 Markdown 走到公开页面

  1. 01

    Authoring

    管理员在 Next.js 后台上传或编辑 Markdown 文件,通过 JWT 与 RBAC 保护文章发布和更新接口。

  2. 02

    Validate

    Go 后端解析 Front-matter,校验 slug、标题、正文长度、标签数量和日期格式,并清洗重复标签。

  3. 03

    Persist

    发布或更新在同一事务中写入 post_translations、修订快照和互动统计,同时双写旧 posts 字段保持兼容。

  4. 04

    Resolve

    Next.js Server Component 请求目标语言版本;Go 存储层优先精确匹配,缺失时回退到中文,并返回可用语言和回退状态。

  5. 05

    Render

    服务端渲染 Markdown、目录、代码高亮和结构化数据;浏览器再通过独立互动接口记录阅读量并处理游客点赞。

03 / ENGINEERING DECISIONS

代码中真实存在的设计

  1. 01

    渐进式迁移,而不是重写后端

    实现公开前端迁移到 Next.js App Router,继续复用 Go/chi REST API、PostgreSQL 和现有文章数据;后端保留旧版 Vue 兼容路由,降低切换期间的破坏性变更。

    价值把迁移风险限制在前端渲染和内容边界,同时让旧站、新站和数据层可以在过渡期共同运行。

  2. 02

    用语言子表承载双语内容

    实现post_translations 以 (post_slug, locale) 作为联合主键,post_translation_revisions 保存每个语言版本的历史快照;读取时由存储层返回 requestedLocale、resolvedLocale 和 fallback。

    价值中英文可以独立发布和更新,语言缺失时不会由前端猜测,而是由后端明确表达回退结果。

  3. 03

    Markdown 解析与版本控制放在后端边界

    实现Go 统一解析 YAML Front-matter,执行 slug、字段长度、标签和时间校验;更新语句携带旧 version,成功后递增版本并写入修订快照。

    价值内容格式和并发更新规则集中在服务端,避免多个管理端同时编辑时发生静默覆盖。

  4. 04

    服务端优先渲染公开内容

    实现Next.js 使用 Server Component 获取文章数据,按语言生成 Metadata、Canonical、alternate、Open Graph、Article JSON-LD、Sitemap 和 RSS;Markdown 通过 GFM、heading slug、代码高亮和目录组件渲染。

    价值把 SEO、首屏内容和阅读结构放回服务端,同时将点赞等个性化互动隔离到客户端请求。

  5. 05

    匿名互动也保持幂等和可控

    实现后端为游客签发 HttpOnly 签名 Cookie,并只在 Redis 与 PostgreSQL 中保存 HMAC 脱敏哈希;点赞由唯一约束和事务保证幂等,浏览量使用日粒度去重,Redis 负责快速过滤和限流。

    价值不要求注册即可回显点赞状态,同时降低刷新、连击和脚本请求对统计数据的影响。

  6. 06

    把可观测性纳入内容服务

    实现Go API 暴露 Prometheus HTTP、数据库和业务指标,并通过可选的 OpenTelemetry OTLP/gRPC 导出 HTTP、数据库和 Redis Span;健康检查、readiness、超时与优雅停机共同管理服务生命周期。

    价值文章请求、翻译回退、互动写入和基础设施瓶颈都有可追踪入口,而不是只依赖用户反馈定位问题。

04 / CURRENT BOUNDARIES

当前仍需继续收敛的边界

这些限制都能从当前代码和部署方式确认,也是下一轮内容平台演进的具体入口。

  1. 高优先级

    旧模型与新模型仍处于双写过渡期

    post_translations 已成为多语言读取和版本管理的主要入口,但 posts 中仍保留旧的中英文列,并在发布更新时同步写入。后续需要确定唯一事实来源并逐步退出兼容双写。

  2. 中优先级

    文章列表的搜索和筛选仍有扩展空间

    当前前端会获取有限数量的文章后完成部分筛选。文章规模扩大后,应将搜索、标签、年份和分页下沉到 Go API,并配合稳定的排序和索引策略。

  3. 中优先级

    内容图片还没有完整的尺寸与优化链路

    Markdown 图片目前以普通 img 渲染,内容没有固有宽高信息。后续需要补充尺寸元数据、响应式加载和 CDN/缓存策略,以继续改善 CLS 和移动端加载。

  4. 中优先级

    Redis 限流是可降级的防护,而不是绝对防刷

    互动接口在 Redis 不可用时会 fail-open,以优先保证博客可用;游客 Cookie 也可能被清除。因此它提供的是基础去重和限流,不应包装成强身份认证或完全防刷系统。

  5. 中优先级

    AI 目前是开发工作流,不是产品能力

    项目可以使用 AI 协助拆解问题、比较方案和验证实现,但当前没有接入 LLM API、RAG、Embedding 或 Agent。案例页不会把这些未实现能力描述成系统功能。

05 / NEXT ITERATION

下一轮应该怎么做

  1. 01

    逐步收敛 post_translations 为唯一内容事实来源,结束旧字段双写

  2. 02

    将搜索、标签筛选、归档和分页下沉到 Go API,并补齐缓存失效策略

  3. 03

    为 Markdown 图片补充尺寸元数据、响应式加载和可观测的 Core Web Vitals 指标

  4. 04

    增加文章发布、语言回退、版本冲突和互动幂等的端到端测试

  5. 05

    完善后台发布审计、回滚和内容发布后的精确缓存刷新流程