跳到主要内容

RYZZ-项目技术评审与改进建议

基于对 RYZZ 全栈代码的深度审查(site 主站、admin 管理后台、public/binding/landPages H5 页面),从工程质量、架构设计、性能、安全、可维护性等维度进行全面评估。


一、做得好的地方

1.1 Monorepo 架构设计优秀

  • Turborepo + PNPM Workspace 的组合成熟稳定,turbo prune --docker 精准裁剪 Monorepo 构建上下文,Docker 多阶段构建充分利用层缓存
  • 8 个公共包(constant、function、hooks、types、contract、login、dauth-web、report-sdk)按职责清晰划分,跨应用复用率高
  • workspace:* 统一版本管理,避免内部包版本漂移
  • Turbo Remote Cache 跨 CI 运行共享构建缓存,显著减少重复构建时间

1.2 WebSocket 通讯系统设计精妙

架构亮点

三层架构(连接管理 → Protobuf 编解码 → 两级事件路由)是整个项目最精巧的设计,新增业务消息类型无需修改传输层和编解码逻辑,开闭原则体现到位。

  • 三层架构(连接管理 → Protobuf 编解码 → 两级事件路由)职责清晰,解耦彻底
  • Protobuf 二进制编码替代 JSON,带宽节省约 50%,90+ 个 proto 定义覆盖全业务
  • 两级事件路由是整个系统最精巧的设计——服务端统一通过 comment 通道下发所有互动消息,客户端按 type 字段二次分发,实现了「单通道多业务」的优雅解耦
  • MessageBatch 批量消息协议降低小消息的网络开销
  • useSubscription / useMsgPushSubscription 自定义 Hook 封装 WS 订阅,业务组件使用简洁

1.3 Web3 集成体系完整且创新

技术深度

DAuth MPC 钱包(2-of-3 分片)+ EIP-4337 账户抽象是整个项目最具技术深度的亮点,完整实现了「Web3 无感化」。

  • DAuth MPC 钱包(2-of-3 分片)+ EIP-4337 账户抽象是整个项目最具技术深度的亮点,让用户通过邮箱/手机号即可拥有链上钱包
  • GG20 多方计算签名协议、密钥恢复机制、Relayer 代提交交易,完整实现了「Web3 无感化」
  • 支持 MetaMask/WalletConnect + DAuth + Google/Twitter 三种登录方式,覆盖面广
  • TransactionReceiver Wrapper 统一处理链上交易签名和确认,避免各业务模块重复实现

1.4 TypeScript 严格模式

  • 基础 tsconfig 配置了 strict: true,从源头保障类型安全
  • Recoil Atom 全部有明确的泛型类型约束和合理的默认值
  • WebSocket 协议路径使用枚举(EReqProtocolPath / ERspProtocolPath)而非魔术字符串

1.5 状态管理设计合理

  • Recoil 原子化状态天然适合直播场景中「频道切换时部分状态重置、部分状态保留」的需求
  • 17+ 个 Atom 按业务域严格分离(currency、channel、betting、gift 等),每个 Atom 独立订阅避免不必要的重渲染
  • 15 层 Provider 嵌套顺序经过精心设计(WagmiConfig → Auth → WebSocket → Currency → Betting),层级间依赖关系清晰

1.6 CI/CD 与部署

  • Docker 四阶段构建 + Next.js Standalone 输出,最终镜像体积小
  • 非 Root 用户运行容器,符合安全最佳实践
  • Kustomize 多环境 Overlay(test / production)配置管理规范
  • PM2 进程管理提供守护和优雅重启

1.7 跨应用第三方登录架构

  • binding 应用作为 OAuth 回调中转站,职责单一且解耦
  • 双通道回调(postMessage 主通道 + Cookie/Focus 降级通道)保障跨浏览器兼容性
  • 四层 Token 交换链路设计严谨,PKCE 防止授权码截获攻击

1.8 其他亮点

  • 阿里云 Aliplayer 帧追赶 + 倍速播放的低延迟直播方案
  • useMemoizedFn(ahooks)避免回调函数重建导致的不必要渲染
  • 三平台埋点(GA + Facebook Pixel + Twitter Conversion)同时上报
  • PageTime 工具记录用户页面停留时长
  • BigNumber 处理链上 Token 余额,避免 JS 浮点精度问题
  • VConsole 仅在 isDebug && isMobile 时动态导入,不影响生产包体积

二、改进建议

2.1 【紧急】安全凭证泄露

安全风险

代码库中存在多处硬编码的安全凭证,需要立即轮换所有已泄露的凭证并迁移到环境变量。

现状:代码库中存在多处硬编码的安全凭证:

文件泄露内容严重程度
.sentryclircSentry Auth Token(sntrys_eyJ...极高 — 可操作 Sentry 项目
src/config/constants/common.tsWalletConnect Project ID,且生产/测试使用同一个值
sentry.client.config.tsSentry DSN 硬编码

风险

  • .sentryclirc 中的 Sentry Auth Token 可被任何有代码读取权限的人用来上传恶意 sourcemap、修改项目配置
  • WalletConnect ID 泄露且生产/测试环境完全相同(isProduction ? A : A 三元表达式无效)

建议

  • 立即轮换所有已泄露的凭证
  • 将凭证迁移到环境变量(process.env.NEXT_PUBLIC_* / CI secrets)
  • .sentryclirc 添加到 .gitignore
  • 使用 git-secretsgitleaks 扫描防止未来凭证提交

2.2 【紧急】target="_blank" 安全风险(41 处)

现状:41 处 <a target="_blank"> 缺少 rel="noopener noreferrer" 属性,且有 2 处 window.open(userCustomUrl) 直接打开用户提交的 URL 无校验。

风险

  • 外部页面可通过 window.opener 操作原始页面(反向点击劫持)
  • 用户提交 javascript: 协议 URL 可导致 XSS

建议

  • 全局搜索 target="_blank" 添加 rel="noopener noreferrer"
  • window.open(url) 前校验 URL 必须以 https:// 开头
  • 安装 eslint-plugin-react 启用 react/jsx-no-target-blank 规则

2.3 【严重】零测试覆盖

稳定性风险

整个项目没有任何测试覆盖,复杂的 Web3 交易逻辑一旦出错可能导致资金损失,WebSocket 核心模块也无测试保护。

现状:整个 RYZZ 项目(site、admin、public、binding、landPages)没有任何单元测试、集成测试或 E2E 测试文件。

风险

  • 每次代码修改都是「盲改」,无法确认是否引入回归 Bug
  • 复杂的 Web3 交易逻辑(DAuth MPC 签名、合约调用)一旦出错可能导致资金损失
  • WebSocket 消息解析、Protobuf 编解码等核心模块无测试保护

建议

  • 优先级最高:为 DAuth MPC 钱包模块(packages/dauth-web)添加单元测试,覆盖密钥生成、恢复、签名、交易执行等核心路径
  • 为 WebSocket 通讯模块(src/utils/websocket/)添加测试,覆盖连接管理、重连、消息队列缓冲、Protobuf 编解码
  • packages/loginuseAuth Hook 添加测试,覆盖三种登录流程
  • 引入 Vitest 或 Jest 作为测试框架,配合 React Testing Library 测试组件
  • 在 CI 中添加测试覆盖率门槛(建议初始目标 30%,逐步提高)

2.2 【严重】WebSocket 重连策略不健壮

现状core.ts 使用固定 5 秒延迟重连,无指数退避、无最大重试次数限制、无网络状态检测。

风险

  • 服务器宕机时客户端每 5 秒发起一次重连请求,大量用户同时重连形成惊群效应(thundering herd),可能压垮恢复中的服务器
  • 无最大重试次数限制,用户在无网络环境下电池持续消耗
  • isReconnectionLoading 标志位虽然防止并发重连,但缺乏防抖保护

建议

指数退避 + 抖动(Jitter)重连策略
实现指数退避 + 抖动(Jitter)重连策略:
- 初始延迟:1 秒
- 最大延迟:60 秒
- 计算公式:delay = min(maxDelay, baseDelay * 2^attempt + random(0, 1000)ms)
- 最大重试次数:20 次(超过后停止重连,提示用户手动刷新)
- 监听 navigator.onLine / online 事件,离线时暂停重连,上线时立即触发
- 监听 document.visibilitychange,页面切到后台时降低重连频率

2.3 【重要】全局错误响应拦截器被注释

现状src/utils/request.ts 中的全局错误响应拦截器被注释掉(// if (data.show) {),导致:

  • 部分 API 错误静默失败,用户无感知
  • WebSocket/index.tsx:62data.show 检查也被注释,所有 push 消息都会触发 message.info

建议

  • 恢复全局错误响应拦截器,统一处理 HTTP 错误和业务错误码
  • 按错误严重性分级处理:网络错误 → Toast 提示 + 自动重试;401 → 自动登出 + 跳转登录;业务错误 → Toast 提示

2.4 【重要】SEO 严重不足

现状

  • 仅首页和 _document.tsx 设置了固定的 <title><meta description>
  • 30+ 个页面路由中,只有首页有独立的 <Head> 标签
  • 直播间页面(/channel/[channelId])未利用 getServerSideProps 获取频道信息注入 meta 标签
  • 缺少 Open Graph / Twitter Card 标签,社交分享时无法展示预览

建议

  • 为每个页面添加动态 <title><meta description>
  • 直播间页面使用 getServerSideProps 获取频道名称、封面图,生成动态 OG 标签
  • 创建 <SEOHead> 通用组件,统一管理 OG、Twitter Card、canonical URL
  • 添加 robots.txtsitemap.xml

2.5 【重要】缺少 ErrorBoundary

现状:整个 site 应用没有 React ErrorBoundary,一个子组件的 JS 错误会导致整个页面白屏。

建议

  • _app.tsx 的 Provider 链最外层添加全局 ErrorBoundary,捕获未处理的渲染错误并展示友好降级 UI
  • 为直播间、创作者后台等核心页面添加局部 ErrorBoundary,隔离错误影响范围
  • ErrorBoundary 的 componentDidCatch 中上报错误到 Sentry

2.6 【重要】Next.js 版本陈旧

现状:使用 Next.js 13.4.1(Pages Router),已落后多个主要版本。

风险

  • 无法使用 App Router、Server Components、Streaming SSR 等新特性
  • 性能优化能力受限(无法使用 next/image 的新优化选项、Turbopack 等)
  • 安全补丁滞后

建议

  • 短期:升级到 Next.js 13 最新 patch 版本,获取安全修复
  • 中期:规划迁移到 Next.js 14+ 的 App Router,利用 Server Components 减少客户端 JS 体积
  • 利用 next/image 替代原生 <img> 标签(当前项目中有大量直接使用 <img> 的场景)

2.7 【中等】Recoil 已停止维护

现状:Recoil(0.7.6)自 2023 年起已基本停止维护(Meta 团队已转向 Relay 和其他方案)。

风险

  • 未来 React 版本升级时可能出现兼容性问题
  • Bug 修复和性能优化停滞
  • 社区生态萎缩,第三方工具支持减少

建议

  • 中长期规划迁移到 Jotai(API 与 Recoil 高度相似,迁移成本低)或 Zustand
  • Jotai 支持与 React Suspense 深度集成,更适合未来 App Router 架构
  • 可以渐进迁移:新功能使用 Jotai,旧功能保持 Recoil,最终统一

2.8 【中等】代码组织可优化

现状

  • useTokenWar.tsx 单文件 24,662 行,是一个「上帝 Hook」,包含注册、排行榜、贡献排名、奖励规则等所有 Token War 逻辑
  • views/Creator/Channel/Live/components/CreatorSide/index.tsx 内部定义 12 个箭头函数,职责过于集中
  • 存在 3 个空 interface IProps {}(InsufficientCoin、AccountSetting、TopUpCoins),增加代码噪音
  • 部分注释掉的 JSX 代码散落在组件中(约 8 处 {/* <Button ... */}

建议

  • useTokenWar.tsx 拆分为 useTokenWarRegistrationuseTokenWarLeaderboarduseTokenWarContributionuseTokenWarRewards 等多个独立 Hook
  • 大组件使用 useReducer 或提取子组件来降低单文件复杂度
  • 清理空接口和注释掉的代码,使用 Git 历史追溯而非代码注释保留旧逻辑
  • 建立代码审查规范:单文件不超过 500 行,单函数不超过 50 行

2.9 【中等】SSR 能力未充分利用

现状

  • 大多数页面的 getServerSideProps / getStaticProps 仅用于获取翻译文件(getTranslationStaticProps),未做任何数据预取
  • 首页使用 getStaticProps,但未生成静态首页内容
  • 直播间等动态页面完全依赖客户端请求数据,首屏白屏时间长

建议

  • 首页 getStaticProps 中预取推荐频道列表和 Banner 数据,结合 ISR(增量静态生成)定期刷新
  • 直播间页 getServerSideProps 中预取频道基本信息(名称、封面、在线人数),减少首屏数据请求
  • 用户资料页使用 getServerSideProps 预取用户信息,提升 LCP

2.10 【重要】Promise 错误被静默吞掉(20+ 处)

现状:大量位置使用 .catch(() => {}) 完全忽略错误:

静默吞掉错误的典型代码
// src/components/TransactionModal/AA/index.tsx
login().then(() => {}).catch(() => {}); // 登录失败完全静默

// src/views/Home/components/Banner/index.tsx
}).catch(()=>{})

// src/views/Creator/Channel/Betting/index.tsx
await login().catch(() => {});

风险:用户操作失败后没有任何提示,无法排查线上问题。

建议

  • 逐一检查 .catch(() => {}) 调用,至少添加 Toast 提示或 Sentry 上报
  • 对于确实需要静默的场景(如预加载),添加注释说明原因

2.11 【重要】两套重复的 HTTP 请求工具

现状:项目同时维护 request.tsrequestLib.ts 两个 Axios 实例,功能几乎完全重复,且 Header 名称大小写不一致(X-LCID vs X-LcidX-DEVICE-ID vs X-Device-Id)。

风险

  • 服务端可能因大小写不同解析不到正确的请求头
  • 两套工具的响应拦截器行为不一致,部分调用手动检查 res.code === 200

建议:统一为一个请求工具,消除重复代码。

2.12 【重要】Aliplayer SDK 静态导入阻塞 SSR

现状src/components/Player/index.tsx 直接 import Aliplayer from 'aliyun-aliplayer',该库是纯浏览器库,静态导入会增大首屏 bundle 且可能导致 SSR 报错。

建议:使用 next/dynamic 动态导入:dynamic(() => import('aliyun-aliplayer'), { ssr: false })

2.13 【中等】moment.js 与 date-fns 重复依赖(~287KB 浪费)

现状:项目同时依赖 moment(~287KB)和 date-fns,其中 moment 仅在 2 个文件中使用(Revenue、CreateTicketCollection),date-fns 在 10+ 个文件中使用。

建议:将 2 处 moment 调用迁移到 date-fns 并移除 moment 依赖,节省约 287KB bundle 体积。

2.14 【中等】react-hot-toast 与 react-toastify 重复

现状:两套 Toast 库同时使用,react-hot-toast 是主要库,react-toastify 使用极少但在 _app.tsx 中挂载了 ToastContainer

建议:统一为一套 Toast 方案,移除另一套。

2.15 【中等】Next.js 图片优化被禁用

现状next.config.jsimages: { unoptimized: true } 关闭了所有图片优化,且有 93 处使用原生 <img> 标签、332 处空 alt=""

建议

  • 开启 Next.js 图片优化,配置 remotePatterns 白名单
  • 将高频展示的图片(频道封面、用户头像等)迁移到 next/image
  • 为功能性图片添加有意义的 alt 描述

2.16 【中等】Sentry 集成不完整

现状

  • sentry.client.config.ts 已初始化但 next.config.js 中的 withSentryConfig 被完全注释掉
  • 导致 source map 无法上传到 Sentry,生产环境错误堆栈无法还原
  • tracesSampleRate: 1 设置为 100% 采样,性能开销大

建议

  • 恢复 withSentryConfig 集成,确保 source map 正确上传
  • tracesSampleRate 调低至 0.1(10%)
  • 验证 Sentry 错误上报是否正常工作

2.17 【中等】定时器泄漏与内存管理

现状SetStreamModalsetTimeout 赋值给外部变量但无 cleanup;useEffect 中有未清理的监听器;useState 存储 Function 类型(应使用 useRef)。

建议

  • 所有 setTimeout/setIntervaluseEffect cleanup 中清理
  • useState<Function> 改为 useRef<(() => void) | null>(null)

2.18 【中等】React Strict Mode 被注释

现状next.config.js 第 7 行 // reactStrictMode: true 被注释掉,无法在开发期间发现副作用问题。

建议:取消注释,启用 Strict Mode。

2.19 【中等】API 文件命名为中文拼音

现状:OpenAPI 自动生成的 API 文件全部使用中文拼音命名(如 shuzihuobixiangguanjiekou.ts),可读性极差。

建议:在 openapi.ts 脚本中配置自定义命名策略(使用英文语义命名)。

2.20 【中等】Recoil 重复 Atom Key 检查被关闭

现状.env 中设置 RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED=false,掩盖了重复 atom key 的潜在问题。

建议:启用检查,排查并修复重复的 atom key。

2.21 【中等】postMessage 缺少来源校验

现状Jackpot 组件监听 window.addEventListener('message') 但未检查 event.origin,可能被恶意页面注入消息。

建议:校验 event.origin 是否为可信域名列表。

2.22 【低等】缺少 Bundle 分析工具

现状package.json 中未配置 @next/bundle-analyzer 或类似工具。

建议

  • 安装 @next/bundle-analyzer,定期分析 bundle 组成
  • 检查 ethers.js 是否可以用更轻量的 viem 替代(项目中已安装 viem 但似乎未完全迁移)

2.23 【低等】国际化硬编码问题

现状

  • 项目支持英文/中文两种语言,使用 next-i18next
  • 部分页面标题(如 _document.tsx 中的 Ryzz - Stream, Earn and Beyond)是硬编码的英文
  • 部分组件内的提示文案可能遗漏翻译

建议

  • _document.tsx 中的固定标题无法国际化(Server 端无 i18n context),但可以在 _app.tsx 中通过 <Head> 动态覆盖
  • 建立翻译键值完整性检查脚本,检测遗漏的翻译键

2.24 【低等】Wagmi v1 已过时

现状:使用 Wagmi v1(1.3.10)+ Web3Modal v2。

风险

  • Wagmi v2 有重大 API 变更,与 Viem v2 深度整合
  • Web3Modal 已更名为 AppKit(由 WalletConnect 团队维护),v3/v4 UI 体验大幅改善
  • 安全更新和 Bug 修复集中在新版本

建议

  • 规划迁移到 Wagmi v2 + Viem v2 + AppKit,获取更好的钱包连接体验和性能
  • 迁移时可以借助 @wagmi/cli 自动生成合约类型

2.25 【低等】缺少 Web Vitals 性能监控

现状:无性能监控(LCP、FID、CLS 等),26 处 console.log/error 散落在生产代码中。

建议

  • 使用 web-vitals 库 + 自有后端埋点收集 Core Web Vitals 数据
  • 添加关键用户路径的自定义性能指标(直播间加载时间、WS 连接建立时间等)
  • 将散落的 console.log 替换为 logger.* 保持一致性

2.26 【低等】NextUI 使用 beta 版本

现状@nextui-org/react: 1.0.0-beta.12,beta 版本在生产环境存在不稳定风险。

建议:升级到 NextUI v2 正式版。

2.27 【低等】大量内联样式(151 处)

现状:151 处 style={{}} 内联样式,动态样式无法被 CSS 引擎缓存。

建议:将可预定义的样式迁移到 Tailwind 类或 CSS Modules,仅保留真正需要动态计算的内联样式。

2.28 【低等】无障碍访问(A11y)缺失

现状

  • 组件中几乎没有 aria-* 属性
  • 自定义弹窗、抽屉等交互组件未实现焦点管理
  • 图片缺少 alt 属性

建议

  • 至少为交互组件(Modal、Drawer、Dropdown)添加基本的 ARIA 角色和焦点管理
  • 图片添加 alt 描述
  • 安装 eslint-plugin-jsx-a11y 自动检测常见无障碍问题

2.29 【低等】Provider 嵌套过深

现状:15 层 Provider 嵌套虽然逻辑清晰,但:

  • 调试时 React DevTools 显示层级极深
  • 某些 Provider(如 Modal、Wallet)的依赖关系不强,可以合并或平铺

建议

  • 考虑使用 compose 函数将多个 Provider 组合,降低 JSX 嵌套深度
  • 评估是否可以将部分 Wrapper(Activity、Betting、Wallet、Modal)合并为单个 InteractiveProvider

2.30 【低等】API/WS 地址硬编码在代码中

现状src/config/constants/common.ts 中 API 和 WebSocket 地址直接通过三元表达式硬编码,无法在不修改代码的情况下更换地址。

建议:使用 NEXT_PUBLIC_API_URL 等环境变量注入,配合 .env.example 文件。

2.31 【低等】环境变量管理

现状

  • 环境变量通过 config/constants/ 集中管理,设计合理
  • .env 文件未被追踪,新开发者需要手动配置

建议

  • 提供 .env.example 文件列出所有必需环境变量及说明
  • 添加启动时环境变量校验(如 @t3-oss/env-nextjs),缺少关键变量时立即报错而非运行时崩溃

三、架构设计层面分析

评审视角

以上的改进建议偏向代码质量细节,本节从更高的技术方案和架构设计视角进行评审。

3.1 架构亮点

3.1.1 WebSocket Protobuf 三层通讯架构

这是 RYZZ 最核心的架构设计,实现了一套完整的实时通讯框架:

WebSocket Protobuf 三层通讯架构
┌─────────────────────────────────────────────┐
│ 应用层:useSubscription / useMsgPushSubscription │
│ → 业务组件只关心「监听哪个事件 + 处理数据」 │
├─────────────────────────────────────────────┤
│ 协议层:protobuf.ts │
│ → reqProtocolMap / rspProtocolMap 双向映射 │
│ → 自动 encode/decode,业务无感知 │
│ → commentTypeMap 二级路由(单通道多业务) │
├─────────────────────────────────────────────┤
│ 传输层:core.ts (Ws class) │
│ → 连接管理 / 心跳 / 重连 / 消息队列缓冲 │
│ → EventEmitter 事件分发 │
│ → MessageBatch 批量消息降低网络开销 │
└─────────────────────────────────────────────┘

设计亮点:传输层完全不关心业务语义,协议层纯粹做序列化/反序列化,应用层通过声明式 Hook 订阅。三层之间通过 path 字符串和 EventEmitter 松耦合,新增业务消息类型只需:

  1. 添加 proto 文件
  2. 在 protocolMap 注册映射
  3. 在组件中 ws.on(path, handler) 监听

无需修改传输层和编解码逻辑,开闭原则体现到位。

3.1.2 "洋葱模型"跨关注点治理

_app.tsx 中 15 层 Provider 嵌套看似夸张,实际上是一种系统化的跨关注点分离架构:

_app.tsx Provider 嵌套顺序
RecoilRoot → Internationalization → NextUIProvider → WagmiConfig
→ Auth → PortalProvider → Page → WebSocket → CustomWrapper
→ Currency → Activity → Betting → Wallet → Modal → Layout

设计思路:每个 Wrapper 只负责一个关注点(认证、国际化、WebSocket 连接、货币数据...),并且严格按依赖顺序排列(例如 WebSocket 必须在 Auth 之后,因为连接需要 token;Currency 必须在 WebSocket 之后,因为余额通过 WS 推送更新)。这让任何单一关注点的修改都不会影响其他层,也便于在开发时逐层关闭调试。

3.1.3 跨应用 OAuth 中枢设计

binding 应用作为独立的 OAuth 回调中转站,解决了"多个前端应用需要对接多个第三方登录提供商"的 N×M 问题:

跨应用 OAuth 中枢架构
site ──┐                   ┌── Google OAuth
admin ─┤── binding 中枢 ──├── Twitter OAuth
mobile ─┘ (统一回调) └── Apple OAuth

双通道回调保障兼容性:
├── 主通道:window.postMessage(现代浏览器)
└── 降级通道:Cookie + window.focus(Safari 隐私限制)

设计亮点:所有 OAuth 回调 URL 统一指向 binding 应用,新增第三方登录只需在 binding 中添加处理逻辑,不需要修改 site/admin/mobile 各自的回调配置。PKCE 流程防止授权码截获攻击。

3.1.4 共享包的职责分层设计

packages/ 共享包职责分层
packages/
├── 基础设施层(无业务语义)
│ ├── constant/ → 环境检测、存储键名
│ ├── function/ → 通用工具函数
│ ├── hooks/ → 通用 React Hooks
│ └── types/ → 跨应用类型定义

├── 业务能力层(封装特定领域能力)
│ ├── login/ → 认证(Web3 + OAuth,跨 site/admin/mobile)
│ ├── contract/ → 智能合约 ABI + TypeChain 类型
│ ├── report-sdk/ → 三平台埋点(GA + Facebook + Twitter)
│ └── dauth-web/ → MPC 钱包 SDK

├── UI 表现层
│ └── ryzz-uikit/ → Ryzz 品牌 UI 组件

└── 工程配置层
├── tsconfig/ → 统一 TypeScript 配置
└── eslint-config-custom/ → 统一代码规范

层级清晰,上层依赖下层,不存在循环依赖。login 包通过 ELoginOrg 枚举支持多应用切换,一套代码服务 site/admin/mobile 三端。

3.1.5 Docker + Turbo Prune 零冗余构建

turbo prune 精准裁剪 Monorepo 构建上下文
# turbo prune site --docker 只提取 site 及其依赖包
# 而不是整个 monorepo 的 30+ 个包
turbo prune site --docker
# ↓ 输出结果:
# out/json/ → 仅 site 相关的 package.json(用于依赖安装缓存层)
# out/full/ → 仅 site 相关的源码
# out/pnpm-lock.yaml → 精简后的锁文件

四阶段构建(base → builder → installer → runner)充分利用 Docker 层缓存,代码不变时依赖安装层完全命中缓存。output: 'standalone' + PM2 运行时保证最终镜像最小化。

3.2 架构改进建议

3.2.1 SSR 能力严重浪费 — Next.js 沦为纯 CSR 框架

现状:项目选择了 Next.js(Pages Router)作为框架,但几乎所有页面的 getServerSideProps / getStaticProps 仅用于加载翻译文件,未做任何业务数据预取。实际上 Next.js 被当作纯 CSR 应用使用。

pages/*.tsx — SSR 仅用于加载翻译
// 当前大多数页面的 SSR 使用方式
export const getStaticProps = getTranslationStaticProps; // 只加载翻译
// 页面数据全部在客户端 useEffect 中获取

架构影响

  • 首屏白屏时间长(HTML 是空壳,所有数据等客户端 JS 执行后才获取)
  • SEO 近乎为零(搜索引擎爬到的是空页面)
  • 浪费了 Node.js 服务端的渲染能力
  • 直播间页面可以通过 SSR 预取频道信息,显著改善 LCP

建议方案

  • 首页:使用 getStaticProps + ISR(每 60 秒重新生成),预取推荐频道列表
  • 直播间 [channelId]:使用 getServerSideProps 预取频道基本信息(名称、封面、在线人数、SEO meta)
  • 用户资料页:使用 getServerSideProps 预取公开用户信息
  • 将「翻译加载 + 业务数据预取」合并到同一个 SSR 函数中

3.2.2 缺乏 BFF 聚合层 — 前端直连 14+ 个微服务

现状:根据 admin/config/openapi.ts,后端有 14 个微服务(live、coin、user、guild、common、trade、report...),前端通过 API Gateway 直接调用所有服务的 API。

当前架构 — 前端直连微服务
前端 ──→ API Gateway ──→ 14 个微服务
(纯透传)

架构问题

  • 一个页面可能需要调用 3-5 个微服务的 API,前端需要自己编排调用顺序和数据聚合
  • 前端承担了过多的数据转换和组装逻辑
  • 移动端和 PC 端对同一数据可能有不同的聚合需求,但只能复用同一批 API
  • 微服务内部接口变动直接影响前端

建议方案: 引入 BFF(Backend For Frontend)层,按端提供聚合 API:

建议架构 — 引入 BFF 聚合层
site    ──→ site-bff     ──→ API Gateway ──→ 微服务
admin ──→ admin-bff ──→ API Gateway ──→ 微服务
mobile ──→ mobile-bff ──→ API Gateway ──→ 微服务

BFF 可以用 Next.js API Routes 实现(零额外部署成本),也可以用独立的 Node.js 服务。BFF 负责:

  • 多微服务数据聚合(一次请求代替前端多次请求)
  • 数据裁剪(只返回前端需要的字段,减少传输量)
  • 隔离微服务接口变动对前端的影响

3.2.3 前端无离线容错架构

现状:作为一个直播 + Web3 应用,完全没有离线容错设计:

  • 无 Service Worker(Next.js 的 next-pwa 未配置)
  • WebSocket 断开时用户无感知,消息静默丢失
  • 网络恢复后无消息补偿机制(不知道断线期间错过了哪些消息)
  • HTTP 请求失败无自动重试,无 Optimistic Update

架构影响

  • 移动端用户在弱网环境下体验极差
  • 直播间断线重连后,错过的礼物特效、评论消息无法恢复
  • Web3 交易提交后网络断开,用户无法知道交易结果

建议方案

  1. WebSocket 消息补偿:重连后发送 lastMessageId,服务端补推断线期间的消息
  2. Optimistic UI:点赞、评论等操作先本地展示,异步同步到服务器,失败时回滚
  3. 请求队列:离线时将操作缓存到 IndexedDB,上线后批量同步
  4. 网络状态感知:全局 NetworkStatus Provider,断网时显示提示横幅

3.2.4 状态管理缺乏持久化和同步策略

现状:17+ 个 Recoil Atom 全部存储在内存中,页面刷新后状态完全丢失。用户认证信息虽然存在 localStorage 中,但业务状态(当前频道、投注状态、钱包信息)全部重新加载。

架构问题

  • 用户刷新页面 = 重新走一遍完整的初始化流程(WS 连接 → 认证 → 进房间 → 拉数据)
  • 多 Tab 之间状态不同步(Tab A 中充值,Tab B 余额不更新)
  • 关键业务状态(如投注进行中)刷新后丢失

建议方案

  1. 分级持久化策略
    • 不持久化:实时数据(在线人数、评论流)
    • SessionStorage:当前会话状态(频道、投注上下文)
    • localStorage:用户偏好(语言、主题、通知设置)
  2. 多 Tab 同步:使用 BroadcastChannel API 在多个 Tab 之间同步余额、认证状态等关键数据
  3. 可以使用 Jotai 的 atomWithStorage 或 Zustand 的 persist middleware 来实现

3.2.5 缺乏特性开关和灰度发布机制

现状:所有功能通过 isProduction 环境变量做开关,没有运行时特性开关。

架构问题

  • 无法对部分用户灰度发布新功能
  • 紧急回滚需要重新部署
  • A/B 测试无基础设施支持
  • Token War、竞猜等高风险功能无法按地区/用户组逐步开放

建议方案: 引入轻量特性开关系统(可以从远端配置中心拉取,也可以基于现有的后端配置服务):

hooks/useFeatureFlag.ts — 特性开关示例
const { isEnabled } = useFeatureFlag('token-war-v2');
if (isEnabled) {
return <TokenWarV2 />;
}
return <TokenWarV1 />;

3.2.6 请求层和 WebSocket 层割裂,缺乏统一的数据获取策略

现状:HTTP 请求(requestLib.ts)和 WebSocket(core.ts)是两套完全独立的通讯系统,没有统一的:

  • 错误处理策略(HTTP 有拦截器,WS 的错误被大量 .catch(() => {}) 吞掉)
  • 重试策略(HTTP 无重试,WS 有重连但无消息重试)
  • 缓存策略(HTTP 无缓存,WS 无消息去重)
  • 认证管理(HTTP 用 Authorization header,WS 用独立的 auth 命令)

建议方案: 建立统一的数据获取层(Data Fetching Layer),将 HTTP 和 WS 统一纳管:

  • 使用 SWR 或 React Query 管理 HTTP 请求的缓存和重试
  • WebSocket 消息与 React Query 的缓存打通(WS 推送 → 自动更新 React Query 缓存)
  • 统一的认证 Token 管理(Token 刷新对 HTTP 和 WS 同时生效)

四、改进优先级矩阵

优先级改进项预估工作量影响范围
P0轮换泄露的凭证(Sentry Token、WalletConnect ID)1 小时安全
P0修复 target="_blank" 安全风险(41 处)0.5 天安全
P0添加核心模块测试(DAuth、WebSocket、useAuth)2-3 周全局稳定性
P0WebSocket 指数退避重连1 天用户体验 + 服务器稳定性
P1恢复全局错误拦截器0.5 天用户体验
P1添加 ErrorBoundary1 天用户体验
P1修复 20+ 处静默 .catch(() => {})1 天可靠性
P1SEO 优化(动态 meta 标签)3-5 天搜索流量
P1修复 Sentry 集成(恢复 withSentryConfig)0.5 天可观测性
P2合并两套 HTTP 请求工具1-2 天代码质量
P2Aliplayer 动态导入0.5 天首屏性能
P2移除 moment.js(节省 ~287KB)0.5 天Bundle 体积
P2开启 Next.js 图片优化2-3 天性能
P2SSR 数据预取1 周首屏加载性能
P2useTokenWar 拆分重构3-5 天代码可维护性
P3Next.js 版本升级1-2 周长期技术栈健康
P3Recoil → Jotai 迁移2-3 周长期技术栈健康
P3Wagmi v1 → v2 迁移1-2 周Web3 体验
P3Web Vitals 性能监控2-3 天可观测性
P3启用 React Strict Mode0.1 天开发质量
P4无障碍访问改进1 周合规性
P4环境变量校验0.5 天开发体验
P4API 文件英文重命名1 天可读性
P4升级 NextUI 到正式版1-2 天稳定性

五、总结

RYZZ 主站是一个技术深度很高的项目——WebSocket Protobuf 通讯系统、DAuth MPC 钱包、EIP-4337 账户抽象等实现都展现了扎实的工程能力和对前沿技术的理解。Monorepo 架构、CI/CD 流水线、多环境部署等工程化实践也相当成熟。

主要短板集中在三个方面:

  1. 安全问题:凭证泄露、target="_blank" 风险、postMessage 无来源校验等需要立即修复
  2. 质量保障缺失:零测试覆盖、无 ErrorBoundary、大量静默 catch 是最大的稳定性风险
  3. 性能优化空间:图片优化被禁用、Aliplayer 静态导入、重复依赖(moment.js、双 Toast 库、双 HTTP 工具)导致 bundle 体积偏大

部分依赖(Next.js 13、Recoil、Wagmi v1、NextUI beta)已进入维护尾期,需要规划技术栈升级。

一句话总结:功能实现能力强,安全加固和质量保障需要优先补齐。