跳转到内容

同一 React/Vite 代码库,不同宿主边界

发布于

WorldScript Studio 用同一套 React/Vite 代码运行 Web、已安装 PWA、边缘托管环境 和 Tauri 桌面应用 版本。作者在 2026 年 9 月 27 日发布的案例分析中介绍了做法:领域概念共用,存储、网络、安全策略和缓存行为则按明确的平台边界选择实现。共享代码库后,这些宿主仍不能互换 (跨 PWA 与 Tauri 的 React/Vite 产品)。

WorldScript Studio 把自己描述为 local-first 创作工作区。仓库说明,它不要求 WorldScript 账号, 也没有中心化稿件数据库;项目状态保存在 browser/PWA 存储或 desktop app 的本地数据目录。仓库还 表示,PWA shell 缓存后,核心写作与规划在离线时仍可使用,而明确需要网络的功能仍然需要连接 (WorldScript Studio README)。

案例把产品模型视为共享层。项目的定义、权威状态、导出语义,以及可选 provider 不可用时的行为, 不应仅因 renderer 宿主不同而改变;这些语义之下的实现机制可以不同。作者给出的规则是共享领域语义 和互操作协议,同时通过显式 adapter 暴露各宿主能力 (跨 PWA 与 Tauri 的 React/Vite 产品)。

React 与 Vite 属于仓库的公共 Web 技术层。README 把 React 列为主 UI,把 Vite 列为 Web/PWA 构建系统,而 Tauri 提供 desktop shell。Tauri 的 Vite 指南直接记录了这种集成:Tauri 可以启动 Vite 开发服务器、执行 Vite build 命令,并通过 tauri.conf.json 设置加载生成的 dist 目录 (Tauri Vite 指南)。

这种集成共享 frontend asset,却没有抹去宿主。Tauri 指南配置不同的开发与生产位置,固定开发 端口,把 Tauri 环境值暴露给 Vite,并为指南列出的 WebView 平台设置构建 target。这些是在同一 frontend 工具链周围作出的宿主感知选择,不能证明 browser tab 与 desktop WebView 拥有相同 API 或相同权限(Tauri Vite 指南)。

仓库的存储表把 browser/PWA 与 Tauri 列赋予不同职责。browser 的项目状态、snapshot 与 asset 使用 IndexedDB,desktop 则使用 app data 下的 local filesystem store。API key 在两边都留在 独立的 IndexedDB 加密 secret store,包括 desktop WebView。表格还表示,受保护的 IndexedDB 项目数据可选择加密,但 filesystem-backed desktop 项目存储没有应用层静态加密 (WorldScript Studio README)。

案例从差异中得出一条产品文案要求:两个控件外观相近,也可能保护不同的持久化路径。真实的 browser 或 filesystem backend 决定数据位置、生命周期和某条加密路径是否适用。共享界面因而需要 标识激活的 backend,不能只凭共同标签承诺相同保护 (跨 PWA 与 Tauri 的 React/Vite 产品)。

浏览器存储 还受 origin 限制。README 表示,GitHub Pages、Vercel、localhost 与 custom domain 部署不会自动共享 IndexedDB 或 model cache。desktop filesystem store 遵循另一套位置与 访问模型。即使用户看到相同 React 界面,产品也不能推断某个 Web origin 保存的数据会出现在另一 部署或 native store 中(WorldScript Studio README)。

报道区分 browser fetch 与 Tauri native HTTP 路径。WorldScript 的 adapter 在 Tauri runtime 选择 native plugin,在其他环境使用 browser fetch。作者用这一差异让 desktop 访问获准的本地 与 cloud endpoint,同时让 browser 请求继续受 origin 规则与 server configuration 约束 (跨 PWA 与 Tauri 的 React/Vite 产品)。

Tauri 把 command scope 记录为细粒度 allow 或 deny 规则。其指南用 filesystem plugin 说明目录 限制,用 HTTP plugin 说明 URL 过滤;还表示 deny scope 优先于 allow scope,并提醒 command 作者审计实现以防绕过。这支持收窄的 capability boundary,但不表示 native request 无需正确配置 与实现就自然安全(Tauri command scope)。

host 也影响 response policy。WorldScript README 表示,GitHub Pages 部署不能注入 HTTP security header,因此在那里依赖 meta CSP;Vercel 部署则可提供 response security header 与 same-origin relay。案例用这个对照说明,相同静态界面也可能运行于不同交付与 server function 保证之下 (WorldScript Studio README)。

这些事实要求 capability check 点名宿主路径。browser 部署可以提供 浏览器存储 与 browser network behavior;边缘托管环境 可以增加 server function 与 response header;Tauri 可以暴露获准的 native command。某个组件出现在 source tree 中,不能单独证明相关能力存在,adapter 与部署配置 共同决定可用路径 (跨 PWA 与 Tauri 的 React/Vite 产品)。

Web surface 使用 Service Worker 提供 cached shell 与 offline fallback。案例表示,Tauri 分支执行 相反动作:取得已有 Service Worker registration 并逐个 unregister,然后枚举 Cache Storage, 删除 WorldScript 自己的 cache name。报道把它解释为避免 stale browser cache 把 offline fallback 覆盖到真实 bundled desktop application 之上 (跨 PWA 与 Tauri 的 React/Vite 产品)。

注销 Service Worker 是这个项目为了区分 缓存中的 Web 应用外壳 和 原生应用包 所作的决定,不能套用到所有 Tauri 应用。你需要确定每个宿主由谁负责离线交付:Web 端如果靠 Service Worker,desktop 端靠 打包后的桌面应用,代码就要明确切换这项职责 (跨 PWA 与 Tauri 的 React/Vite 产品)。

宿主差异对存储和发布测试的影响

链接到“宿主差异对存储和发布测试的影响”一节

这个案例提供了一条位于「万能实现」与「完全不同产品」之间的具体路径。产品实体与文件格式可以 共享;存储、网络传输、离线交付、安全策略与操作系统集成可以置于收窄的宿主 adapter 后面。这样 能让平台差异在影响用户数据与能力的位置保持可见 (跨 PWA 与 Tauri 的 React/Vite 产品)。

对于已安装 PWA,安装不会把 origin-scoped browser data 变成 native filesystem store。 WorldScript 自身的 matrix 仍把 PWA 路径写为 浏览器存储,把 Tauri 路径写为 filesystem persistence。这项区别影响 migration、backup、recovery、加密承诺,以及 UI 对项目保存位置的表述 (WorldScript Studio README)。

同一原则也适用于依赖网络的功能。cached PWA shell 可以加载,但可选 remote provider、协作服务、 model 首次下载或其他网络集成仍可能不可用。WorldScript README 明确区分 offline-capable 核心写作 与需要连接的功能。产品状态应分别描述这些能力,不能把 shell 可用当成每项集成都已就绪的证据 (WorldScript Studio README)。

测试可以沿用同一张边界图。共享 domain test 可以建立不变的项目语义;adapter test 可以确认选择 了哪种持久化与 transport;宿主 integration test 再分别覆盖 browser origin、Service Worker lifecycle、Tauri scope 和 filesystem behavior。来源没有提供普遍适用的 test suite,但其架构让 这些职责可以分别观察 (跨 PWA 与 Tauri 的 React/Vite 产品)。

文档也必须保持同样精确。仓库警告,不应把某一部署行里的保证泛化到另一行。功能说明需要点名哪个 host 提供 storage、header、server function、native transport 或 offline behavior。这样才能防止 一个关于单一 build target 的真实陈述,变成错误的全产品承诺 (WorldScript Studio README)。

发布资格同样不能只看共享的 Web pipeline。README 明确表示,普通 Web PR pipeline 并不是完整的 native release qualification surface;涉及 native 或 Tauri 的修改需要专用 desktop build workflow 及其平台证据。仓库还区分 updater artifact 使用的完整性签名与操作系统 code signing, 并分别点名 Windows Authenticode 和 macOS Developer ID signing/notarization。共用前端构建 通过后,桌面应用发布仍有独立的宿主级验证责任,两类签名路径不能互相替代 (WorldScript Studio README)。

WorldScript Studio 采用「共享契约、选择实现、说明边界」的做法。存储表、部署说明、fetch adapter、Tauri scope 和 Service Worker teardown 都明确列出了共同 React/Vite 界面下的差异。共享界面并不能做到「构建一次,到处行为相同」 (跨 PWA 与 Tauri 的 React/Vite 产品)。

  • WorldScript Studio 是否会在参考 revision 后改变任何 adapter、backend 或部署边界,尚未确认。
  • 另一个 React/Vite 与 Tauri 产品是否应采用相同存储分工,尚未确认。
  • 该项目 browser store 与 desktop filesystem store 之间的 migration 路径,尚未确认。
  • 每个可选 provider 在各种 offline transition 下的行为,尚未确认。
  • 项目 native release workflow 在各平台上的结果,尚未确认。
  • 项目未来 desktop roadmap 是否保留相同 Tauri 边界,尚未确认。