# Cloudflare 部署与性能优化方案(全盘) > 目标:前端可通过 Cloudflare 域名访问;后端(Supabase / LightRAG / ingest_service / Redis 等)通过 Cloudflare Tunnel 或等价方式对外暴露;同时解决当前“页面切换卡顿”的体感问题,并为后续 OCR(MinerU)与 RAG 自动入库留出扩展空间。 ## 0. 现状结论(基于当前代码扫描) ### 0.1 当前代码对 Cloudflare(Edge/Workers/Pages)的直接阻塞点 `wolai-frontend` 内存在大量 Node 内置依赖与本地文件系统读写(`fs/path/process.cwd()`),例如: - `wolai-frontend/src/lib/mindmap-files.ts`、`wolai-frontend/src/app/api/mindmap/**`:读写 `public/documents` / `public/mindmaps` 下的本地文件 - `wolai-frontend/src/app/api/documents/{create,duplicate,copy-tree}`:本地文件写入/拷贝 - `wolai-frontend/src/lib/ai/onlineAiConfig.ts`:本地读取配置文件 - 部分 API 还使用 `crypto.randomUUID` 这些在 Cloudflare Pages/Workers 的运行时中**不可用或不推荐**(没有传统 Node 文件系统/进程工作目录概念),因此“把整个 Next.js(含 API Routes)直接部署到 Cloudflare 并保持当前行为”会遇到现实阻碍。 ### 0.2 当前“页面切换卡”的高概率根因 在改造前,`/documents/[id]` 会把 `documents.content` 作为 Server Component props 直接带到前端编辑器(BlockNote)。当 `content` 较大时,会显著增加: - 服务器到浏览器的 RSC Flight payload 体积 - 浏览器端 JSON 解析、反序列化与 hydration 负担 这类卡顿会在“切换不同页面”场景中放大。 > 已落地修复:`/documents/[id]` 不再直接携带 `documents.content`,改为客户端按需请求 `/api/documents/content` 后再加载编辑器内容(见下方“P0 优化已实现”)。 --- ## 1. Cloudflare 部署拓扑:推荐的三种路径 ### 路径 A(推荐优先):Cloudflare 仅做反代/加速,本地跑完整 Next(含 API) **适用场景**:希望最少改代码、尽快可用;允许前端与 API 都跑在你本地/服务器(Docker),Cloudflare 只提供域名与隧道入口。 - Cloudflare Tunnel 将 `https://你的域名` 指向本地的 `wolai-frontend`(Next server) - `/api/*` 也由同一 Next server 提供(无需跨域) - Supabase/LightRAG 等服务同样通过 Tunnel 暴露(可用子域名或路径分流) **优点** - 几乎不需要重构(保留 `fs`/本地 mindmap 文件体系) - cookie / session 同源,前端调用 `/api` 最简单 **缺点** - 首屏与静态资源仍取决于你本地带宽/延迟(可通过 Cloudflare 缓存静态资源缓解) - 需要你保证本地服务稳定在线 ### 路径 B:Cloudflare 部署“纯静态前端”(SPA/静态 Next),API 全部回源到本地 **适用场景**:希望前端 CDN 化(加载快),后端服务仍由你本地/服务器提供;愿意做一定的前后端解耦与配置改造。 关键改造点: - 前端不能依赖 Next Server Components 的“服务器取数”,而应改为客户端请求后端 API - Next 的 `app/api/*` 要迁移到后端服务(或保留在本地 Next,但需要确保 Cloudflare Pages 的 `/api` 反代到本地) - 所有本地文件读写(mindmap 文件、copy-tree)必须移动到“后端服务”中执行 **优点** - 前端体验更好(静态资源全球 CDN) - 后端仍可保留现有 Node 能力(fs、pdf 处理、脚本等) **缺点** - 需要统一“API Base URL / 反代规则 / CORS / cookie 域” - 需要规划“哪些 API 放在本地 Next,哪些独立成后端服务” ### 路径 C:Cloudflare 运行 Next(Workers/Pages Functions)+ 后端回源 **适用场景**:希望尽可能多逻辑在 Cloudflare 边缘,但愿意严格约束 Node 能力,重构较大。 现实结论:以当前代码结构(大量 `fs/path/process.cwd()`)来看,除非先做较大改造,否则不建议直接走该路径。 --- ## 2. 性能优化路线图(按优先级) ### P0(已实现,立刻收益):文档内容按需加载,减小路由切换负担 已改动: - 新增 `GET /api/documents/content?documentId=...`:仅返回 `documents.content` - `/documents/[id]` 不再 `select content`,避免 RSC 携带大字段 - 编辑器内容在客户端加载:`DocumentContent` 在 `initialContent==null` 时拉取内容并展示“页面内容加载中...” - `BlockNoteEditor` 在 `normalizedInitialContent` 变化时重新初始化(只会从 `null -> 实际内容` 触发一次) 预期收益: - 切换页面时,RSC payload 更小、解析更快 - 为 Cloudflare 反代/跨网访问(带宽较差)场景奠定基础 ### P1(强烈推荐,低风险高收益):侧边栏与文件树性能 1) 文件树虚拟列表 - `FileTree` 当前对 `rows` 直接 `map` 渲染,文档/附件数量上来后会明显卡顿 - 已有 `@tanstack/react-virtual` 用例(`PrivateTree`),可复用同一技术栈把 `FileTree` 也做虚拟化 2) `assetsByDoc` 构建从 O(n^2) 优化为 O(n) - 当前实现每次 push 前会 `some()` 去重(n 较大时会变慢) - 建议改为 `Map>` 一次遍历构建 3) `/api/sidebar` 数据裁剪与拆分 - `fetchSidebarDataset` 对 `media_assets` 使用 `select("*")`,字段过多会拉大 payload - 建议改为只取侧边栏需要字段;并进一步拆分: - 文档树(documents) - 垃圾桶(trashed docs/assets) - 附件列表(只取当前展开节点/或按 docId 批量懒加载) ### P2(中期):文档内容存储与传输优化(大文档体验) 1) 内容分片/分页加载(可选) - 对 `documents.content` 进行“块级分页”(例如按顶层 block 分块),在编辑器侧逐步加载 2) 只拉取必要字段 - 页面切换只拉 meta(title/updated_at/options/stats),内容按需加载(已完成) - backlinks / history 等面板可延迟加载或切换时懒加载 3) 缓存与压缩策略(配合 Cloudflare) - 对静态资源启用强缓存(Cloudflare 默认可做) - 对“用户私有”接口设置 `Cache-Control: private`,避免被共享缓存污染 - 对“公开内容(public pages)”可用 `s-maxage` + `stale-while-revalidate` --- ## 3. Cloudflare 反代/穿透下的关键工程点(必须规划) ### 3.1 统一 API 入口与路径分流 建议以同一域名提供: - `https://mnote.example.com/`:前端 - `https://mnote.example.com/api/*`:后端 API(本地 Next 或独立服务) - `https://mnote.example.com/supabase/*`:如需(或直接使用 supabase 子域名) - `https://mnote.example.com/lightrag/*`:LightRAG 7777(建议仅内部/鉴权后暴露) 这样可以最大化减少 CORS 与 cookie 域问题。 ### 3.2 上传链路必须“直传” Cloudflare/反代链路对大文件上传很敏感: - 建议前端改为“拿签名 URL 后直传到 Supabase Storage”(你已有 `/api/media/signed-url`) - 避免通过前端服务器中转大文件(会受 CF/反代限制、也会拖慢) ### 3.3 本地文件系统能力的迁移策略 当前 mindmap 文件存储在 `public/documents/**` 本地目录,这对 Cloudflare 部署不友好。 两条路: - 保留“本地 Node 后端”(路径 A / B),让所有文件读写都在本地后端做 - 或迁移到 Supabase Storage(推荐长期):mindmap 变成一个可版本化的对象文件(支持软删/回收站/延迟清理) --- ## 4. 观测与量化(否则很难证明“不卡了”) 建议先落地最小可用的观测: 1) 前端导航耗时 - 在 `router.push` 前后打点(`performance.mark`),记录到 console 或上报 2) 关键 API 延迟 - `/api/sidebar`、`/api/documents/content`、`/api/search/*`:记录开始/结束与 payload 大小 3) 体感指标 - 首次可交互(TTI) - 文档打开到“编辑器可输入”的时间 --- ## 5. 下一步执行清单(建议按顺序) 1) 选择 Cloudflare 部署路径(A/B/C) 2) P1:`FileTree` 虚拟化 + `assetsByDoc` O(n) 化 + `/api/sidebar` select 裁剪 3) P2:公开页面缓存策略、上传直传、mindmap 存储迁移方案