Files
next-ai-draw-io/docs/cn/cloudflare-deploy.md
T
Dayuan Jiang 60105ddb51 refactor: remove dead code and over-engineering found by two audits (#986)
## Problem

Two audits of the repository (a workflow of finder, dedup and per-file verifier agents, run on 2026-10-11 against 1f4141e and again against 07f3e3c after a first round of refactoring) found dead code and features that were more machinery than the app needs: an Electron configuration-preset system with its own settings window, three copies of the about page, a hand-written `.env` parser, an "extended" system prompt nobody selected, two data migrations for formats from 2025-12 and 2026-01, a server-side example cache, type-to-confirm provider deletion, 81 unused dictionary keys, wrapper components around single call sites, and a long tail of unused exports, props, options and tests.

## Change

Every item below was either approved one by one or covered by "fix all of the others".

- **Electron:** the configuration-preset system is gone (settings window, preload, IPC, menu entry, dev watcher); `config-manager.ts` keeps only `userLocale`; `.env` files are parsed with `dotenv`. Entitlements file and a duplicate CI workflow removed; `test.yml` gets a type check and concurrency.
- **Server:** no extended prompt, no example cache, no `ENABLE_HISTORY_XML_REPLACE`, no message metadata or `hasConfig`; the connection test is one shared helper; EdgeOne loses its mock branch and model aliases; `DEBUG_LLM_PAYLOAD` logs message structure instead of payloads; Langfuse scoring helper; `apiKeyEnv` arrays kept and documented in `env.example` and the provider docs.
- **Pages:** one about page per language from a single component (old `/cn` and `/ja` URLs redirect with 308); layout uses `hasLocale`; the GitHub icon is a local component instead of `react-icons`; Cloudflare deploys without an R2 cache by default.
- **Chat and canvas:** the legacy `diagramHistory` conversion, the localStorage chat migration and the templates storage are gone; `chat-engine` reads the diagram through the context's refs; the diagram context has one tagged export path (`requestTaggedExport` / `fetchDiagramXml`); the screenshot check uses fetch + JSON and `generateText` with `Output.object`; `load-diagram` accepts `<svg:svg>` and strips the XML prolog.
- **Settings UI:** `model-selector` inlines its Dialog, Command and Tooltip; `ai-elements/model-selector`, `button-with-tooltip`, `error-toast` removed; no type-to-confirm, no footer, no `bedrockApiKey`; `use-model-config` loses the old-format migration; one reasoning component; the shimmer is CSS (no `motion`, no `@radix-ui/react-use-controllable-state`); 81 dictionary keys removed in all four languages.
- **MCP server:** `registerTool` / `ok` / `fail` replace per-tool try/catch; `syncFromBrowser`, `commitDocument`, `describePages`; the hand-written XML syntax check, unused result fields, `pickPageSelector`, `expandStyles` and the `host` attribute handling are gone; tests get a shared `setup.ts` and drive the server through the SDK client.
- **Prompt:** the web app's style rules come from the MCP drawing guide (`styleRules`), byte-identical to before.
- **Tests:** shared e2e helpers (`openApp`, `sse`, `toolCallEvents`, `chunkedReplies`); placeholder specs dropped; `settings-review-fixes` split by topic; unit tests use `vi.stubEnv`.
- **Dependencies removed:** `@xmldom/xmldom`, `remark-gfm`, `@anthropic-ai/tokenizer`, `@testing-library/user-event`, `concurrently`, `wait-on`, `eslint`, `eslint-config-next`, `@vitest/coverage-v8`, `shx`, `motion`, `@radix-ui/react-use-controllable-state`, `react-icons`.

Source lines: 74,983 before, 67,418 after (excluding lockfiles).

The last commit merges #984 (the canvas shell). Where the shell, the classic page or their tests depend on a wire format or signature this branch had changed, main's version wins (export fields of the poll response, `addHistory` signature); where main only extended code this branch restructured, main's change is carried into the new structure (`start_session`, `get_selection`, `prepareNewDiagram`, the diagram context's `requestExport`).

## Testing

- `tsc --noEmit` for the web app, `packages/mcp-server`, its shell and `electron`: clean
- `biome ci`: 0 errors (37 pre-existing warnings)
- Root `vitest run`: 719 passed; `packages/mcp-server` `vitest run`: 372 passed
- `next build`: clean
- Playwright, whole web suite on the dev server (4 workers): 280 tests, 279 passed; `language.spec.ts` "a stale offer to switch without saving does nothing once a message is being sent" failed under parallel load and passed alone, as it does on main
2026-10-12 12:35:55 +09:00

5.8 KiB
Raw Blame History

部署到 Cloudflare Workers

本项目可以通过 OpenNext 适配器 部署为 Cloudflare Worker,为您提供:

  • 全球边缘部署
  • 极低延迟
  • 免费的 workers.dev 域名托管
  • 通过 R2 实现完整的 Next.js ISR 支持(可选)

Windows 用户重要提示: OpenNext 和 Wrangler 在 原生 Windows 环境下并不完全可靠。建议方案:

  • 使用 GitHub Codespaces(完美运行)
  • 或者使用 WSL (Linux)

纯 Windows 构建可能会因为 WASM 文件路径问题而失败。


前置条件

  1. 一个 Cloudflare 账户(免费版即可满足基本部署需求)
  2. Node.js 18+
  3. 安装 Wrangler CLI(作为开发依赖安装即可):
npm install -D wrangler
  1. 登录 Cloudflare:
npx wrangler login

注意: 只有在启用 R2 进行 ISR 缓存时才需要绑定支付方式。基本的 Workers 部署是免费的。


第一步 — 安装依赖

npm install

第二步 — 配置环境变量

Cloudflare 在本地测试时使用不同的文件。

1) 创建 .dev.vars(用于 Cloudflare 本地调试 + 部署)

cp env.example .dev.vars

填入您的 API 密钥和配置信息。

2) 确保 .env.local 也存在(用于常规 Next.js 开发)

cp env.example .env.local

在此处填入相同的值。


第三步 — 选择部署类型

选项 A:不使用 R2 部署(默认,免费)

仓库自带的就是这套配置:open-next.config.ts 为 defineCloudflareConfig({}),wrangler.jsonc 中没有 r2_buckets。无需改动任何文件,直接跳至 第四步。


选项 B:使用 R2 部署(可选,用于 ISR 缓存)

R2 为 OpenNext 提供存放 增量静态再生 (ISR) 页面的空间。本应用目前没有 ISR 页面,只有在您自己添加了此类页面时才需要这一步。需要在您的 Cloudflare 账户中绑定支付方式。

1. 在 Cloudflare 控制台中创建 R2 存储桶:

  • 进入 Storage & Databases → R2
  • 点击 Create bucket
  • 命名为:next-inc-cache

2. 配置 open-next.config.ts:

import { defineCloudflareConfig } from "@opennextjs/cloudflare/config"
import r2IncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache"

export default defineCloudflareConfig({
  incrementalCache: r2IncrementalCache,
})

3. 在 wrangler.jsonc 中加入 r2_buckets:

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "main": ".open-next/worker.js",
  "name": "next-ai-draw-io-worker",
  "compatibility_date": "2025-12-08",
  "compatibility_flags": ["nodejs_compat", "global_fetch_strictly_public"],
  "assets": {
    "directory": ".open-next/assets",
    "binding": "ASSETS"
  },
  "r2_buckets": [
    {
      "binding": "NEXT_INC_CACHE_R2_BUCKET",
      "bucket_name": "next-inc-cache"
    }
  ],
  "services": [
    {
      "binding": "WORKER_SELF_REFERENCE",
      "service": "next-ai-draw-io-worker"
    }
  ]
}

重要提示: bucket_name 必须与您在 Cloudflare 控制台中创建的名称完全一致。

注意: 定时重新验证(页面或 fetch 上的 revalidate)还需要在 open-next.config.ts 中配置 queue,请参阅 OpenNext 的 Cloudflare 缓存文档。


第四步 — 注册 workers.dev 子域名(仅首次需要)

在首次部署之前,您需要一个 workers.dev 子域名。

选项 1:通过 Cloudflare 控制台(推荐)

访问:https://dash.cloudflare.com → Workers & Pages → Overview → Set up a subdomain

选项 2:在部署过程中

运行 npm run deploy 时,Wrangler 可能会提示:

Would you like to register a workers.dev subdomain? (Y/n)

输入 Y 并选择一个子域名。

注意: 在 CI/CD 或非交互式环境中,该提示不会出现。请先通过控制台进行注册。


第五步 — 部署到 Cloudflare

npm run deploy

该脚本执行的操作:

  • 构建 Next.js 应用
  • 通过 OpenNext 将其转换为 Cloudflare Worker
  • 上传静态资源
  • 发布 Worker

您的应用将可通过以下地址访问:

https://<worker-name>.<your-subdomain>.workers.dev

常见问题与修复

You need to register a workers.dev subdomain

原因: 您的账户尚未注册 workers.dev 子域名。

修复: 前往 https://dash.cloudflare.com → Workers & Pages → Set up a subdomain。


Please enable R2 through the Cloudflare Dashboard

原因: wrangler.jsonc 中配置了 R2,但您的账户尚未启用该功能。

修复: 启用 R2(需要支付方式)或使用选项 A(不使用 R2 部署)。


No R2 binding "NEXT_INC_CACHE_R2_BUCKET" found

原因: wrangler.jsonc 中缺少 r2_buckets 配置。

修复: 添加 r2_buckets 部分或切换到选项 A(不使用 R2)。


Can't set compatibility date in the future

原因: wrangler 配置中的 compatibility_date 设置为了未来的日期。

修复: 将 compatibility_date 修改为今天或更早的日期。


Windows 错误:resvg.wasm?module (ENOENT)

原因: Windows 文件名不能包含 ?,但某个 wasm 资源文件名中使用了 ?module。

修复: 在 Linux 环境(WSL、Codespaces 或 CI)上进行构建/部署。


可选:本地预览

部署前在本地预览 Worker:

npm run preview

总结

功能 不使用 R2 使用 R2
成本 免费 需要绑定支付方式
ISR 缓存 无 有
静态页面 支持 支持
API 路由 支持 支持
配置复杂度 简单 中等

仓库默认 不使用 R2。只有当您添加了需要 ISR 缓存的页面时,才选择 使用 R2。