Files
rainblogweb/docs/v2-plan.md
T

11 KiB
Raw Blame History

RainWeb v2 全面升级计划

v1(原生 HTML/CSS/JS + PJAX)→ v2React 前后台分离 + 后端改造)。用户确认的选型全部定案,本计划为唯一执行依据。 旧 docs/refactor-plan.md 的后端部分(P0/P1/P2 中安全与数据库项)并入本计划;其前端路由项(P1-14 方案 A、P2-19 方案 B作废——由 React Router 取代。 本计划未开始任何代码改动,待用户确认后按阶段执行。

0. 选型定案(已确认,不再变更)

决定
前端框架 React + ViteTS 可选,见 §4.1
前台 UI 不引 UI 库,手写组件 + 复用 public/css/style.cssUI 100% 还原
后台 独立应用(独立入口 /admin),引入 MUI
工程组织 单 Vite 项目多入口(前台 + 后台两个 HTML 入口)
SEO 保留 ssr.js 双轨/blog/:id、/forum/:id、sitemap.xml 不变)
数据库 better-sqlite3 + Node 22 LTS(替换 sql.js
后端改造 原 P0 止损 + P1 安全加固照旧执行

1. 目标架构

浏览器
 ├── 前台 SPA(/            React + React Router,构建产物 + style.css,占位符机制保留
 │     └── 导航「管理后台」按钮 → 整页跳转 /admin(浏览器级导航,非 SPA 路由、非 iframe
 ├── 后台 SPA/admin       React + MUI,完全独立入口/独立路由/独立登录态,外部面板嵌入保留
 └── SEO 直链(/blog/:id 等) ssr.js 服务端渲染(不变)
          ↓
Express 4server.js
 ├── /api/* 15 个路由模块(契约不变,前端重写以现有 API 为基)
 ├── 静态:构建产物 + uploads/ + public/wallpaper/
 └── SPA fallback/ → 前台 index.html/admin* → 后台 index.html
          ↓
better-sqlite3data/rainweb.db,零迁移直接打开)

前后台关系:两个独立 React 入口(单 Vite 多入口构建),互相之间仅通过整页跳转连接。前台无后台路由、后台无前台路由;登录态共用(同一 JWT,localStorage)。

2. v1 → v2 保留 / 废弃清单

保留:后端全部(routes/、middleware/、db.js 逻辑、ssr.js、cli.js 改造后)、public/css/style.css(搬入前台)、public/wallpaper/uploads/、API 契约。

废弃public/index.html 等全部页面 HTML(改 React 组件)、public/js/ 全部(api/nav/router/theme/captcha/render/music-embed/main/blog/forum/admin/passwords → 拆成 React 模块)、PJAX 机制(router.js)、public/js/main.js 等死代码。

保留功能点(迁移时必须覆盖):博客瀑布流、论坛多分类/子分类/发帖回复、密码管理器(PIN + AES-256-GCM,见 §4.4)、管理面板聚合(iframe 嵌入 + proxy 代理)、壁纸/磨砂玻璃/深浅色主题、音乐嵌入(自动隐藏)、验证码(内置/recaptcha)、邮箱验证注册、公告、附件上传([image:]/[file:] 标签渲染)。

3. 阶段划分(每阶段验证 + commit,可随时暂停)

Phase 0 后端止损(≈半天,独立)

  • P0-1 删除 Web 更新链路(server.js /api/update/check + /api/update/run、admin.js 前端引用、cli.js zip 分支)→ 消除 RCE 面 + .git 覆盖风险
  • P0-2 JWT_SECRET 启动生成随机值写入 .env.json(消除 R4 硬编码密钥)
  • P0-3 /api/setup/complete 加 adminOnly/setup/status 移除 default_password(消除 R5 接管)
  • P0-4 /api/proxy/fetch 加 adminOnly + 私网地址过滤(消除 R3 SSRF)
  • P0-5 邮件验证码不回显 + 修复 pending 重建 bug(消除 R7
  • 验证:curl 逐项(未登录 401、内网 URL 拒绝、响应无 code)

Phase 1 后端安全加固(≈1-1.5 天)

  • P1-1 上传白名单 + /uploads 防护头(R1
  • P1-2 内容净化:ssr.js + 后端出口统一 DOMPurify/转义(R2 服务端侧;前端侧随 v2 组件实现)
  • P1-3 登录/发帖限流 + 服务端验证码校验(R8express-rate-limit
  • P1-4 密码箱解锁限流 + PBKDF2 600kM1
  • P1-5 adminOnly 查库复查、草稿权限、错误信息收敛、rejectUnauthorized 收敛、avatar 白名单(M2-M7 中后端项)
  • P1-6 cli.js 统一到 db.js(消除双封装 + data.db 路径分裂)
  • P1-7 schema_version 迁移框架(幂等补列 + PRAGMA user_version
  • 验证:curl 安全用例 + node cli.js status/config/password 正常

Phase 2 数据层换轨 better-sqlite3(≈1 天,依赖 P1-6/P1-7

  • 前置:Node 升 22 LTS(宝塔 Node 版本管理器);README/Docker 示例同步
  • db.jsnew Database(DB_PATH) 同步初始化;run/get/all 重写(prepare + info.lastInsertRowid);删 saveDb/exportinitTables 保留幂等补列
  • routes/import.js:上传文件落临时路径只读打开
  • 数据零迁移:现有 data/rainweb.db 直接打开;PRAGMA integrity_check 预检
  • 验证:备份 → 启动 → CRUD 走查 → cli 命令 → sqlite3 命令行直查

Phase 3 前端工程化搭建(≈1 天)

  • 项目根新建 frontend/Vite + React + React Router;多入口:index.html(前台)+ admin.html(后台))
  • 共享层:api 客户端(封装现有 /api/*token 仍 localStorage,错误处理统一)、工具(escapeHtml/日期/分页)、主题(深浅色状态管理)
  • style.css 迁入前台入口;${site_name} 等占位符保留在构建模板中(serveIndex 运行时替换机制不变)
  • Vite 配置:构建产物输出到 public/dist/base: '/';多入口 rollupOptions
  • package.json scriptsdevvite)、buildvite build)、startserver.js
  • 验证:dev server 起得来、两个入口都能打开、HMR 正常

Phase 4 前台页面迁移(≈3-4 天,核心工作量)

按页面迁移为 React 组件,视觉逐页对照还原

  1. 布局壳(导航栏/主题切换/壁纸/磨砂玻璃)+ React Router 路由表(/、/blog、/forum、/passwords、/login、/register、/profile、/write、/forum-manage、/embed、/setup);导航栏「管理后台」按钮 = 整页跳转 /admin<a href="/admin">,不走 SPA 路由)
  2. 首页(瀑布流、侧栏头像/简介、最新文章)→ 原 HOMEPAGE 逻辑
  3. 博客(列表/详情/编辑,markdown + [image:]/[file:] 渲染 → 组件化 DOMPurify 净化)
  4. 论坛(分类/子分类/发帖/回复/详情)
  5. 密码管理器(PIN 解锁、加密交互,见 §4.4)
  6. 登录/注册(验证码、邮箱验证流程)
  7. 个人中心(头像上传、资料编辑)
  8. 音乐嵌入、公告、其他全局组件
  • 验证:逐页对照 v1 截图/行为走查;无控制台报错

Phase 5 后台独立应用(≈2 天)

  • MUI 后台(/admin):完全独立入口与路由;入口方式 = 前台导航「管理后台」按钮整页跳转(Phase 4 已建);后台内可返回前台(跳转 /)
  • 登录态守卫(未登录跳转 /login,JWT 与前台共用);布局(侧栏导航 + 顶栏)
  • 页面:仪表盘、站点设置(含主题/壁纸/玻璃参数)、博客管理、论坛管理、用户管理、公告、面板链接(嵌入 + proxy 代理保留)、验证码/邮件配置、上传管理、密码箱(admin 视角)、更新检查入口移除(P0-1 已删)
  • 原 admin.js 600 行的逻辑按 MUI 组件重写
  • 验证:后台全功能走查 + 前台联动(改设置 → 前台生效)

Phase 6 集成上线(≈1 天)

  • server.js:静态服务指向构建产物;SPA fallback 分流(/admin* → 后台入口,其余 → 前台入口);serveIndex 占位符对构建产物生效
  • 旧 public/*.html 与 public/js/ 全部退役删除(ssr.js 引用除外——核对 ssr.js 是否引用 style.css/占位符,保留所需)
  • SEO 双轨验证:/blog/:id、/forum/:id、sitemap.xml、robots.txt 行为不变
  • 部署流程更新:宝塔 = npm install → npm run build → npm start
  • README/AGENTS.md 全量更新(v2 架构、命令、构建链说明)

4. 关键技术决策

4.1 TypeScript

默认不用 TS(v1 全 JS,单人无测试,减少迁移摩擦);如用户要 TS 可启用(React + Vite TS 模板),代价是迁移工作量 +20%。→ 计划默认 JS,待确认。

4.2 构建产物与占位符

Vite 构建产物 index.html 保留 ${site_name}/${site_description}/${site_favicon} 文本,serveIndex 运行时替换机制不变(构建模板中写占位符即可)。后台入口同理。

4.3 路由与 fallback

  • 前台:React Routerhistory 模式),server.js app.get('*') 回前台入口
  • 后台:/admin 前缀路由,server.js 增加 /admin* → 后台入口(注意在 SPA catch-all 前)
  • SSR 路由(/blog/:id、/forum/:id)优先级高于 SPA fallback(现状已如此,保持)

4.4 密码管理器加密

v1 为"服务端保管密钥"模型(PIN 明文到服务端派生)。v2 前台重写时默认保持行为不变(服务端派生 + PBKDF2 600kPhase 1 已加固)。真正 E2EWebCrypto 客户端派生)列为 v2 后续可选项,不在本次范围。

4.5 音乐嵌入

v1 的 music-embed(自动隐藏、位置、超时)迁移为 React 全局组件,行为参数从 site_settings 读取,逻辑照搬。

4.6 验证码

captcha.js 前端逻辑(内置 SVG 验证码 + recaptchaReact 化;服务端校验在 Phase 1 已接通(P1-3)。

5. 验证策略(无测试环境)

  • 每阶段:curl API 用例 + 浏览器手动走查 + node cli.js 命令
  • Phase 4/5:逐页对照 v1 行为清单(§2 保留功能点逐项打勾)
  • 上线前:完整回归清单(登录/发帖/上传/密码箱/主题/面板嵌入/SEO 直链)
  • 可选:引入 Vitest + React Testing Library 对共享层(api 客户端、渲染函数)补少量单测——默认不做,待确认

6. 风险与回滚

风险 缓解
前端重写回归(11 页功能面广) 阶段化推进、§2 功能清单逐项走查;v1 代码保留到 Phase 6 验收通过再删
密码管理器迁移出错 加密逻辑独立模块化迁移,Phase 4 单独验收
better-sqlite3 换轨 数据零迁移 + 备份 + PRAGMA 预检;失败可随时回滚 db.js(v1 代码在 git 历史)
构建链引入部署变化 Phase 6 单独验收部署流程;devvite dev+ prodbuild)双路径文档化
SEO 回归 ssr.js 双轨不变,Phase 6 专门验证直链

7. 工时总览

阶段 内容 工时
Phase 0 后端止损 0.5 天
Phase 1 后端安全加固 + cli 统一 + 迁移框架 1-1.5 天
Phase 2 better-sqlite3 换轨 1 天
Phase 3 前端工程化搭建 1 天
Phase 4 前台页面迁移 3-4 天
Phase 5 后台独立应用(MUI 2 天
Phase 6 集成上线 + 文档 1 天
合计 9.5-11.5 天

每阶段结束:验证清单通过 → git commit → 可暂停验收。