Files
SuBlog/docs/react-go-content-platform-selection.md
T

13 KiB

React + Go 内容平台技术选型

状态:提案

更新时间:2026-07-19

适用范围:SuBlog 从 Markdown 静态博客演进为可运营的内容系统。

1. 目标与边界

目标

  • 提供公开的文章阅读、搜索、归档、标签、系列、SEO 和评论体验。
  • 提供受权限控制的运营后台,支持文章草稿、发布、定时发布、修订、媒体上传和用户管理。
  • 保留当前博客的视觉识别:技术图标环绕头像、主题切换动画、轻量内容阅读体验。
  • 将业务规则、鉴权和数据一致性收敛到 Go 服务,前端不持有业务写入逻辑。

不在第一阶段解决

  • 多租户、计费、复杂工作流和实时协同编辑。
  • 微服务、消息队列和 gRPC。
  • 直接把 Nuxt/Vue 组件转换为 React 组件。

首版采用模块化单体:一个 Next.js 应用、一个 Go API、一个 PostgreSQL 实例和一个 S3 兼容对象存储。先保证内容链路可靠,再按真实运营需求拆分。

2. 结论

采用以下组合:

层级 选型 决策
Web 前端 Next.js App Router + React + TypeScript 采用
样式与基础组件 Tailwind CSS + shadcn/ui 采用
视觉动效 Magic UI 采用,仅用于体验增强
后台服务 Go + Gin 采用
数据库 PostgreSQL 采用
媒体存储 S3 协议对象存储,开发环境使用 MinIO 采用
内容编辑器 首版 Markdown;富文本需求明确后引入 Tiptap 延后
API 契约 OpenAPI 3.1 + TypeScript 客户端生成 采用
服务端状态 TanStack Query,仅用于后台的客户端交互 采用

Next.js 的 App Router 默认使用服务端组件,适合将公开文章页在服务端从 Go API 获取数据后输出 HTML,同时把编辑器、筛选和管理表单限制在客户端组件中。Next.js Server and Client Components

shadcn/ui 的组件代码进入项目而非被黑盒依赖包封装,适合作为长期维护的后台设计系统;Magic UI 则只用于图标云、主题切换等差异化效果,不作为后台基础组件。shadcn/ui Introduction Magic UI Icon Cloud

3. 总体架构

flowchart LR
  Visitor["读者"] --> Web["Next.js Web\n公开站点与运营后台"]
  Operator["运营人员"] --> Web
  Web -->|"SSR / HTTPS API"| API["Go API\n鉴权与业务规则"]
  API --> DB[("PostgreSQL")]
  API --> Storage[("S3 / MinIO\n媒体资源")]
  API --> Events["内容发布事件"]
  Events --> Revalidate["Next.js 缓存失效端点"]
  Revalidate --> Web

生产环境使用同一主域名,反向代理按路径分流:

https://example.com/        -> Next.js
https://example.com/admin/  -> Next.js
https://example.com/api/v1/ -> Go API

这样浏览器访问 API 不需要 CORS,Go 可使用 HttpOnlySecureSameSite=Lax 的会话 Cookie。Next.js 仅负责渲染、路由和 API 调用适配;文章发布、权限判断、文件签名和数据写入只能由 Go 服务完成。

4. React 前端设计

4.1 框架职责

区域 渲染方式 数据方式 说明
首页、文章页、归档、标签、系列 Server Components 优先 Next 服务端请求 Go API SEO、首屏和分享信息优先
搜索、评论、主题切换、头像图标云 Client Components 按需调用 API 仅加载必需的浏览器逻辑
/admin Client Components 为主 TanStack Query 调用 Go API 表格、筛选、编辑和乐观更新
登录页 Server + Client Components Go 会话 API 不在浏览器保存访问令牌

TanStack Query 管理后台的远程数据缓存、重新获取和写入后的失效;公开页面不为此引入客户端状态层,直接使用 Next 的服务端数据获取和缓存策略。TanStack Query Queries

4.2 UI 与视觉系统

以 Tailwind CSS 的语义变量作为唯一主题来源,先定义 backgroundforegroundcardmutedborderprimary 等 token,再由 shadcn/ui 和业务组件共同消费。不要将页面色值散落在组件中。

Magic UI 的定位是“效果层”,使用范围限定为首页品牌区、空状态和少量内容提示;文章正文、后台表格、表单和弹窗保持克制、信息密度优先。

现有视觉资产迁移

现有能力 当前实现 React 迁移方案 可复用范围
技术图标环绕头像 vue-icon-cloud + CSS Magic UI IconCloud 图标 slug、图片 URL、尺寸与视觉参数可复用;Vue 组件代码不可复用
主题切换 Vue useColorMode + View Transitions API next-themes 管理主题状态,Magic UI AnimatedThemeToggler 负责动画 动画原点、时长、prefers-reduced-motion 降级和 CSS token 可复用
深浅色样式 CSS 变量 globals.css 的 Tailwind/shadcn token 色彩语义和视觉值可复用,选择器需重写

现有项目并没有直接使用 Magic UI:头像云是 Vue 专用组件,主题切换是自行封装的 View Transitions API。React 端可直接采用 Magic UI 对应组件的实现路径,官方提供了 IconCloud 和基于 View Transitions API 的主题切换组件。Magic UI Theme Toggler

4.3 内容编辑策略

首版以 Markdown 为正文规范,延续现有文章资产并降低导入风险:

  • 后台编辑器保存 body_markdown,预览由与公开页面一致的渲染器生成。
  • 文章的标题、摘要、标签、发布时间、封面和状态使用结构化字段保存。
  • 每次保存创建修订快照,发布操作产生不可变的发布记录。

当存在非技术作者、复杂嵌入内容或协同编辑的明确需求时,再评估 Tiptap。Tiptap 提供 React 集成和可组合扩展,但其 Markdown 能力仍处于 beta 文档范围,因此不将它作为首版 Markdown 数据规范的前提。Tiptap Editor

5. Go 后端设计

5.1 模块边界

apps/api/
├── cmd/api/                 # 程序入口、依赖装配、优雅退出
├── internal/
│   ├── identity/            # 用户、角色、会话、登录限制
│   ├── content/             # 文章、标签、系列、草稿、修订、发布
│   ├── media/               # 上传策略、文件元数据、对象存储
│   ├── site/                # 站点设置、导航、主题等运营配置
│   ├── audit/               # 管理操作审计日志
│   ├── platform/            # 数据库、缓存、对象存储、时钟、ID
│   └── transport/http/      # Gin 路由、鉴权中间件、请求/响应 DTO
├── migrations/              # 仅追加的数据库迁移
└── openapi/                 # OpenAPI 源文件与生成配置

业务模块拥有自己的服务、仓储接口和测试;HTTP handler 只做参数绑定、鉴权调用和响应映射。禁止 handler 直接拼接 SQL,禁止前端绕过 Go 直接访问数据库或对象存储。

5.2 首版数据模型

实体 关键字段 说明
users idemailstatus 运营用户身份
roles / user_roles rolepermission RBAC,首版至少管理员、编辑、只读
sessions token_hashexpires_atuser_id 服务端会话,不将访问令牌写入 localStorage
posts slugtitlesummarybody_markdownstatuspublished_at 文章当前版本
post_revisions post_idcontentcreated_by 草稿与发布前可回滚快照
tags / post_tags slugname 标签关系
media object_keymime_typesizecreated_by 文件元数据,文件本体在对象存储
audit_logs actor_idactiontargetmetadata 发布、删除、授权等关键操作记录

文章状态固定为 draftscheduledpublishedarchived。状态流转在 content 模块校验,数据库事务内同时更新文章、修订和审计日志。

5.3 API 与契约

  • 使用 /api/v1/public/* 提供公开只读接口,例如文章详情、归档、标签、站点配置。
  • 使用 /api/v1/admin/* 提供后台接口,并按角色授权。
  • 以 OpenAPI 3.1 为唯一接口契约,从契约生成 React TypeScript 客户端;Go handler 的集成测试验证响应符合契约。
  • 发布、下线、删除、媒体上传等写入接口要求会话、CSRF 防护、审计日志和幂等键。
  • 发布成功后,Go 使用签名事件调用 Next.js 缓存失效端点;不得依赖固定时间等待缓存过期。

6. 仓库结构

迁移完成后采用 pnpm workspace 与 Go 模块并存的单仓库:

sublog/
├── apps/
│   ├── web/                 # Next.js
│   │   ├── app/
│   │   │   ├── (public)/
│   │   │   └── admin/
│   │   ├── components/
│   │   │   ├── ui/          # shadcn/ui 受控源码
│   │   │   ├── effects/     # Magic UI 及品牌动效
│   │   │   └── content/
│   │   ├── lib/api/         # 生成的 API client 与查询封装
│   │   └── styles/
│   └── api/                 # Go 服务
├── contracts/openapi/       # API 契约
├── deploy/                  # Compose、反向代理、生产部署说明
├── scripts/migrate-content/ # 现有 Markdown 导入工具
└── docs/

现有 content/posts/<slug>/index.md 仅作为迁移输入和归档备份;迁移完成后,运行时内容的唯一来源是 Go API + PostgreSQL。

7. 分阶段迁移

阶段 0:技术验证

完成一条最小闭环:Go 提供一篇文章的公开读取接口,Next.js 服务端渲染文章详情,Magic UI 图标云和主题切换在 React 中正确运行。

验收:SEO 元信息可见、首次加载无主题闪烁、禁用动效偏好下主题可正常切换。

阶段 1:公开内容迁移

  1. 建立 PostgreSQL 迁移、poststagspost_revisions 和公开 API。
  2. 编写一次性导入脚本,读取现有 frontmatter 和 Markdown 正文。
  3. 重建首页、文章详情、列表、归档、标签和系列页面。
  4. 保留原 URL,缺失页面使用 301 重定向,逐页比对标题、描述、封面和正文。

验收:全部已发布文章可访问;迁移前后的 URL、SEO 字段和图片链接无回归。

阶段 2:运营后台

  1. 建立登录、会话、RBAC 与审计日志。
  2. 实现文章列表、草稿编辑、预览、发布、定时发布和修订回滚。
  3. 接入对象存储的预签名上传与媒体选择器。
  4. 接入内容发布事件与 Next.js 缓存失效。

验收:编辑只能操作授权资源;发布后公开页与 sitemap 在可预期时间内更新;审计记录可追踪。

阶段 3:运营能力完善

  • 后台搜索、内容质量检查、死链检测与站点设置。
  • 评论审核、内容推荐和访问统计。
  • 基于实际作者需求决定是否引入 Tiptap、协同编辑或内容审批流。

8. 关键风险与验证

风险 影响 MVP 验证
Markdown 导入丢失格式 历史内容不可逆受损 保留原文件,导入后逐篇 hash 与人工抽检
Next 缓存未失效 发布后读者仍看到旧内容 发布接口后调用签名失效端点,编写端到端测试
前后端职责混杂 规则分散且难以审计 代码审查禁止 Next Route Handler 承载业务写入
富文本过早引入 数据格式和编辑器维护成本暴涨 首版只验证 Markdown 编辑与预览
动效影响后台可用性 性能与无障碍下降 Magic UI 仅在品牌区域使用,尊重 prefers-reduced-motion

9. 测试与上线标准

  • Go:领域服务单元测试、HTTP + PostgreSQL 集成测试、迁移升级测试、权限矩阵测试。
  • Web:组件测试覆盖主题与编辑表单;Playwright 覆盖登录、草稿、发布、撤回、文章访问和上传。
  • 契约:CI 生成 TypeScript API client,并检测 OpenAPI 变更。
  • 发布:健康检查、数据库备份、对象存储生命周期规则、错误监控和审计日志保留策略齐备后才接入真实运营数据。

10. 最终决策

React + Go 适合本项目向内容平台演进,但必须以“Next.js 负责体验与渲染、Go 负责全部业务与数据”为边界。优先迁移公开阅读链路,再实现后台闭环;不要在第一阶段同时重写全部页面、接入富文本和实现复杂工作流。