用 Next.js 和 Cloudflare Workers 构建浏览器本地工具站:架构、隐私与性能取舍

简介: 记录一个Next.js在线工具站在浏览器本地计算、Web Worker任务隔离、Cloudflare Workers部署、增量缓存和工具模块化方面的实现与取舍。

最近我在开发一个在线工具站。项目叫 ToolExo,目前公开页面中包含计算器、开发者工具、图片处理和 PDF 工具等多个类别。

工具站看起来简单:输入内容,点击按钮,返回结果。但工具数量增加以后,问题很快就不只是“再写一个表单”了。

我需要处理几个相互关联的问题:

  • 用户输入应该在哪里计算?
  • 图片、PDF和文本是否必须上传服务器?
  • 如何防止某个复杂任务卡住整个页面?
  • 一百多个工具如何共用页面结构,同时保持各自逻辑独立?
  • Next.js应用部署到Cloudflare Workers后,动态内容和缓存如何配合?

这篇文章记录目前采用的方案,以及其中几处比较实际的取舍。

一、先划定数据边界:能在浏览器完成,就不上传

这个项目最早确定的一条规则是:适合在浏览器完成的任务,默认在浏览器处理。

比如:

  • JSON格式化
  • 正则表达式测试
  • Base64编解码
  • UUID和密码生成
  • 图片压缩与尺寸调整
  • PDF合页面拆分、合并和旋转
  • 普通数学计算

这类操作没有必要先把数据发给服务器,再把结果传回来。

以JSON格式化为例,完整流程可以留在当前页面中:

export function processJson(
  input: string,
  options: {
   
    mode: "format" | "minify" | "validate";
    indent?: "2" | "4" | "tab";
    sortKeys?: boolean;
  },
) {
   
  if (input.trim().length === 0) {
   
    return {
   
      ok: false,
      message: "请先输入 JSON",
    };
  }

  if (input.length > 1_000_000) {
   
    return {
   
      ok: false,
      message: "输入内容超出当前工具限制",
    };
  }

  try {
   
    const value = JSON.parse(input);

    return {
   
      ok: true,
      output:
        options.mode === "minify"
          ? JSON.stringify(value)
          : JSON.stringify(value, null, 2),
    };
  } catch (error) {
   
    return {
   
      ok: false,
      message:
        error instanceof Error
          ? error.message
          : "JSON 解析失败",
    };
  }
}

这里没有API请求,也没有数据库写入。输入、解析和输出都发生在浏览器中。

下载结果时同样可以使用浏览器提供的Blob URL,不需要先生成服务器文件:

function downloadJson(value: string) {
   
  const blob = new Blob([value], {
   
    type: "application/json;charset=utf-8",
  });

  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");

  link.href = url;
  link.download = "formatted.json";
  link.click();

  URL.revokeObjectURL(url);
}

实际版本还限制了输入长度、JSON嵌套深度和用于展示的节点数量。限制不是为了制造功能缺口,而是为了防止一次异常输入耗尽浏览器内存。

可以在JSON Formatter中看到这套交互。

二、本地处理不等于把所有任务塞进主线程

文件处理或文本分析放在浏览器里,还有一个常见问题:JavaScript执行时间太长时,页面会失去响应。

例如,一个设计不当的正则表达式可能产生大量回溯。如果直接在React事件处理中运行,输入框、按钮和页面滚动都会受到影响。

因此,正则测试器没有直接在主线程里执行表达式,而是为每次任务创建一个Web Worker:

function createRegexJob(request: RegexRequest) {
   
  const worker = new Worker(
    new URL("./regex-worker.ts", import.meta.url),
    {
    type: "module" },
  );

  const timer = setTimeout(() => {
   
    worker.terminate();
  }, 500);

  worker.postMessage({
   
    id: crypto.randomUUID(),
    request,
  });

  worker.addEventListener("message", (event) => {
   
    clearTimeout(timer);
    worker.terminate();

    console.log(event.data.result);
  });
}

上面的代码经过了简化。项目中的实际实现还处理了:

  • Worker启动失败
  • 用户连续修改表达式时取消旧任务
  • 零长度匹配
  • Unicode模式
  • 匹配数量上限
  • 替换结果长度限制
  • uv标志互斥
  • 潜在高回溯结构提示

Web Worker可以在与主线程分离的执行环境中运行脚本,适合处理可能占用较长时间的任务。不过Worker不能直接操作DOM,主线程和Worker之间需要通过消息传递数据。MDN Web Worker文档

)

这里有一个容易忽视的细节:Web Worker只能隔离任务,不能自动解决正则表达式拒绝服务问题。

如果Worker里的表达式一直运行,浏览器仍然会消耗CPU。项目因此设置了500毫秒的执行上限,到时直接终止Worker。这个限制比较保守,但在线测试工具首先要保证页面不会被一个表达式拖死。

对应实现可以在Regex Tester中体验。

三、服务器负责交付页面,不参与不必要的计算

前端本地计算并不代表整个网站只能做成纯静态站点。

项目当前采用的主要技术包括:

Next.js
React
TypeScript
Cloudflare Workers
OpenNext Cloudflare适配层
Cloudflare R2
Durable Objects
Neon PostgreSQL

职责大致分为三层。

浏览器

浏览器负责适合本地运行的工具逻辑:

输入
  ↓
边界校验
  ↓
本地计算或Web Worker
  ↓
结果展示
  ↓
用户主动复制或下载

工具输入默认不会因为计算而进入数据库。

Next.js应用

Next.js负责:

  • 页面路由
  • 服务端和静态页面生成
  • Metadata
  • canonical
  • 结构化数据
  • 分类和相关推荐
  • 文章页面
  • 管理端服务逻辑

工具的计算引擎一般写成独立TypeScript模块。React组件处理界面状态,计算引擎处理输入规则和业务逻辑。

这种分离带来的直接好处是:计算引擎不依赖DOM,单元测试也不需要启动浏览器。

// engine.ts
export function calculate(input: ToolInput): ToolResult {
   
  // 输入检查和计算
}

// component.tsx
const result = calculate(formValue);

Cloudflare与数据库

Cloudflare Workers负责运行Next.js应用和处理请求。项目当前使用OpenNext的Cloudflare适配方案,并保留R2增量缓存和Durable Object重验证队列。

简化后的配置如下:

import {
    defineCloudflareConfig }
  from "@opennextjs/cloudflare";

import r2IncrementalCache
  from "@opennextjs/cloudflare/overrides/incremental-cache/r2-incremental-cache";

import doQueue
  from "@opennextjs/cloudflare/overrides/queue/do-queue";

export default defineCloudflareConfig({
   
  incrementalCache: r2IncrementalCache,
  queue: doQueue,
  enableCacheInterception: true,
});

Neon PostgreSQL主要保存工具目录、文章、发布状态和管理数据,而不是保存用户粘贴到工具里的JSON、文本或文件。

公开页面优先读取缓存内容,避免每次访问都查询数据库。定时发布等后台任务则通过Cloudflare Cron Trigger进入受控流程。

需要说明的是,Cloudflare当前针对新Next.js项目的文档已经把vinext列为默认建议;已有OpenNext项目则可以继续查看其他部署路径。技术选型需要结合项目的现有兼容性和迁移成本,不能只看最新示例就立即替换生产链路。Cloudflare Next.js部署文档 OpenNext Cloudflare文档

四、一百多个工具不能等于复制一百多个组件

批量建设工具页时,最容易出现两种极端。

第一种是所有工具都独立开发。这样自由度高,但页面结构、错误状态、可访问性和SEO设置会逐渐失控。

第二种是所有工具强行套用同一个动态表单。开发速度快,但复杂工具很快会被模板限制,代码里也会出现大量条件判断。

项目最后采用了中间方案:

共享页面外壳
├── 标题和简介
├── 分类导航
├── 隐私提示
├── 使用步骤
├── 方法或公式说明
├── FAQ
├── 相关文章
└── 结构化数据

独立工具模块
├── 输入类型
├── 校验规则
├── 计算引擎
├── 特定交互
├── 结果展示
└── 导出方式

普通计算器可以复用统一页面外壳。JSON、正则、PDF、图片等交互差异较大的工具,则保留独立组件。

共享的是稳定规则,不是业务逻辑本身。

五、本地工具仍然需要安全限制

“没有上传服务器”只能说明一部分隐私边界,不能直接等同于“绝对安全”。

浏览器工具仍然需要处理:

  • 超大输入造成的内存占用
  • 恶意PDF或异常图片
  • 正则表达式高回溯
  • CSV公式注入
  • 文件名和MIME类型不一致
  • 用户输入进入HTML时造成XSS
  • Blob URL未及时释放
  • 旧任务结果覆盖新任务
  • 浏览器能力不完整

项目使用固定输入上限、显式格式检查和任务取消机制。用户输入通过React普通文本节点显示,不把任意输入拼进HTML。

页面还设置了CSP、X-Content-Type-OptionsReferrer-Policyframe-ancestors等响应头。不过这些响应头只能降低部分风险,不能替代输入校验和安全的业务实现。

对于无法稳定在浏览器完成的任务,正确做法也不是悄悄切换到服务器。界面应该先说明:

  • 文件是否上传
  • 上传到哪里
  • 保存多久
  • 谁可以访问
  • 任务完成后什么时候删除

目前ToolExo仍以浏览器优先处理为主,可以从项目首页查看公开工具分类。

六、实际开发中最容易踩的几个坑

把“本地运行”写成一句宣传语

如果页面宣称文件不会上传,代码里就不能存在隐藏的上传请求、远程分析SDK或自动持久化行为。隐私说明必须能从网络请求和源代码中验证。

只限制文件大小,不限制计算复杂度

一个体积很小的输入也可能造成高CPU消耗,例如嵌套正则、深层JSON或结构异常的压缩文件。长度、深度、节点数、执行时间和输出规模需要分别限制。

为了共用模板而牺牲工具边界

JSON格式化和正则测试都属于开发者工具,但它们的风险模型和交互方式完全不同。共享颜色、按钮和页面结构没有问题,强行共享同一套业务状态通常会让代码更难维护。

只测试正确输入

工具最重要的测试经常不是“1+1是否等于2”,而是:

  • 空输入如何处理
  • 超限输入是否提前停止
  • 浏览器缺少某项能力时是否有明确提示
  • 任务被取消后是否仍更新旧结果
  • 导出文件是否与页面结果一致

这些测试比增加一段营销文案更能提高工具的可信度。

结语

做在线工具站以后,我对“简单工具”有了新的理解。

公式本身往往不难。真正花时间的是数据边界、异常输入、浏览器兼容、任务取消、结果解释和测试。工具数量增加后,架构的价值也不在于少写几行代码,而在于让新工具继承已有的隐私、安全和质量约束。

项目还在继续完善。后面我准备单独整理浏览器端PDF处理、图片元数据清理,以及正则表达式超时隔离的实现细节。

参考资料

  1. Cloudflare:在Workers上运行Next.js
  2. OpenNext Cloudflare文档
  3. MDN:使用Web Worker
  4. MDN:Blob
  5. MDN:URL.createObjectURL
相关文章
|
1天前
|
人工智能 自然语言处理 安全
阿里云AI数智鉴密:AI 生成内容如何拿到一张"防篡改的身份证"
隐形水印 + C2PA签名:让AI生成内容“持证上岗”。
1084 0
|
9天前
|
人工智能 自然语言处理 安全
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
本文聚焦阿里云2026年推出的三款自研AI办公产品,清晰拆解千问办公、Qoder Teams、Qoder CN的差异化定位与能力边界:千问办公主打职场全场景提效,支持自然语言指令一键完成PPT生成、数据分析等高频办公任务;Qoder Teams面向程序员团队,深度整合AI代码生成、团队协同与企业知识库能力;Qoder CN则专为金融、政务等强合规场景打造,实现数据不出境与VPC私有化部署。文章同步给出分场景选型指南与最新活动定价,帮助不同类型的企业按需组合产品,实现业务岗、研发岗与强合规场景的AI能力全覆盖。
3593 3
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
|
21天前
|
人工智能 缓存 前端开发
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
DeepSeek Harness + DeepSeek V4 Pro 项目实战保姆级教程!手把手带你从零安装开源 AI 编程工具,开发架构图、知识讲解网站、3D 网页游戏、全栈 AI 应用 4 个项目,覆盖运行模式选择、插件安装与开发,看看能不能对标 Claude。
13325 91
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
|
15天前
|
Web App开发 人工智能 API
16 个超火的 DeepSeek Harness 插件,大肥鱼已经落后 N 个版本了。。。
DeepSeek Harness 精选插件推荐合集,从图片识别、浏览器操控、多 Agent 协作到手机远程控制,一口气带你看完 DSH 社区热门的十几个插件,覆盖技能扩展、UI 界面增强、整活玩法三大类,让你的鲸鱼变得更强。
1851 4
|
7天前
|
人工智能 监控 测试技术
Qwen3.8-Flash 来了,100万上下文、Agent、Coding 都加强了
8月26日,通义千问发布Qwen3.8-Flash-Next:125B参数、每Token仅激活6B,原生支持26万Token、可扩展至100万上下文;Coding、Agent与工具调用能力显著增强,面向真实软件工程任务,推动大模型从“回答问题”迈向“完成工作”。
|
10天前
|
人工智能 Linux iOS开发
Ollama使用教程:Ollama官网下载、Ollama本地部署大模型(2026最新)
Ollama 是一款免费开源的本地大模型运行工具,支持在 Windows/macOS/Linux 上离线运行 Qwen、DeepSeek、Llama 等主流开源模型,数据不出本机、隐私安全。提供 OpenAI 兼容 API,命令行一键拉取/运行/管理模型,无需联网,无调用限制,是开发者与 AI 爱好者部署本地 AI 助手的理想选择。(239 字)
|
16天前
|
人工智能 Java BI
【AI】DeepSeek Harness 安装、运行、管理插件
本文介绍了如何运行DeepSeek开源的Agent框架DeepSeek Harness(dsh)。主要内容包括:使用nvm安装适配的Node版本;通过代理加速克隆GitHub源码;使用pnpm安装依赖并启动项目;配置DeepSeek API Token;安装扩展功能的插件。该框架自带Web界面,支持模型适配、文件编辑等插件化功能
2049 1

热门文章

最新文章