最新资讯
dev.to 部署 Underdog Bark 3.0 Pro:逐字转写、自定义后端与分块设置 dev.to 为艰难对话构建 AI:五个 Agent、一条安全正则与一位盲评监督者 techcrunch.com Palo Alto Networks 洽谈以 5 亿美元收购 AI Agent 安全初创公司 Clutch theinformation.com 黄仁勋被要求就涉华间谍指控向国会作简报 www.infoq.com Edera 推出 Object Capability Bounded Authority,试图将凭证与 AI Agent 工作负载隔离 wechat 这波杀疯了!旗舰级模型不限量、1个月视频额度免费领 bloomberg.com AI 抛售蔓延至信用市场,软银领跌亚洲美元债 dev.to 如何在专用 GPU 服务器上用 OpenAI 兼容 API 部署 LLM dev.to 审计 153 份 Claude Code 与 Codex 会话记录:User-Agent 与 URL 中的邮箱泄露 dev.to 你的 Agent Harness 应具备的 17 项能力 dev.to 离线 AI 记忆中 0.8 余弦阈值为何失效 dev.to Kimi K3.1 Pro 开放权重:自托管 2.8T 模型前的开发者清单
多元动态
登录 注册
大模型 dev.to · @qnbs

同一套 React/Vite 产品横跨 PWA 与 Tauri:不假装两者完全相同

原文 我的收藏

文章以 WorldScript Studio 为例,说明同一 React/Vite 代码库可同时部署为 GitHub Pages 站点、已安装 PWA、边缘托管应用和 Tauri 桌面应用,但这些运行面并非可互换。作者主张共享领域语义与互操作契约,通过显式适配器暴露平台能力,而非用统一抽象掩盖差异。文中给出各部署面的能力与限制对比:GitHub Pages 无法注入任意 HTTP 安全响应头,只能用 meta CSP 作为唯一执行点;Vercel/Cloudflare Pages 可设置真实响应头并运行同源边缘中继(如 api/claude-proxy.ts);PWA 存储仍受浏览器源限制;Tauri 桌面端提供文件系统持久化和原生 HTTP,但桌面项目文件目前未做静态加密。代码引用来自 commit 2d9157c0、release v1.28.8。

AI推荐理由 这是一篇有具体代码引用(commit 2d9157c0、release v1.28.8)和明确部署对比表的工程实践文章,讨论同一 React/Vite 代码库在 GitHub Pages、PWA、边缘托管和 Tauri 桌面端之间的能力与安全边界差异,并给出“共享领域语义、用显式适配器暴露平台能力”的可操作原则。其价值在于对跨端架构、CSP 头限制、存储与文件系统权限边界的实际经验总结,对做 AI 应用/桌面端/离线产品的开发者有参考意义。局限是案例来自单一项目 WorldScript Studio,属经验分享而非可复现的基准或官方规范,且未提供性能或安全性的量化验证。

62

正文

One React/Vite codebase can power a GitHub Pages site, an installed PWA, an edge-hosted deployment, and a Tauri desktop app. That does not make those surfaces interchangeable. This distinction matters whenever an application handles user projects, offline behavior, AI providers, filesystem access, or security policy. Shared components are valuable. Shared assumptions can be dangerous. WorldScript Studio is a useful case study because its React/Vite application is intentionally available across browser/PWA and Tauri desktop environments. The product shares domain semantics, but it does not pretend that a browser tab and a native shell have the same authority boundaries. Code references are from the repository at commit 2d9157c0 (2026-09-28), release v1.28.8; simplified excerpts are labeled. Share the product model, not every implementation detail A cross-platform product needs a stable answer to questions such as: What is a project? What data belongs in it? Which state is authoritative? What does export mean? What should happen when an AI provider is unavailable? Those answers should be shared. The mechanisms underneath them should not be forced to look identical. For a PWA, the browser provides IndexedDB, Cache Storage, service workers, Web APIs, WebGPU, and origin-scoped storage. A desktop shell can provide application-data filesystem access, native networking, OS integration, and platform packaging. Trying to hide every difference behind a single universal abstraction often creates a worse outcome: browser APIs leak into desktop code, native assumptions leak into web code, and the product accumulates several accidental definitions of persistence or network policy. A better rule is: Share domain semantics and interoperability contracts. Expose platform capabilities through explicit adapters. The host changes the security boundary The same static build can be deployed to different hosts, but hosting changes what the application can guarantee. Surface Important capability Important limitation GitHub Pages Static public deployment Cannot inject arbitrary HTTP security headers Vercel / Cloudflare Pages Response headers and edge-function capabilities Still browser-origin storage for web project data Installed PWA Cached shell and browser-native installation Storage remains origin- and browser-specific Tauri desktop Filesystem persistence and native HTTP Desktop project files are not currently app-encrypted at rest GitHub Pages is a good example of why "deployed from the same source" is not enough. WorldScript uses a meta Content Security Policy there because GitHub Pages cannot add the corresponding response headers — the project's deployment documentation calls that meta tag the sole enforcement point on that host. Vercel and Cloudflare Pages can set real response headers that mirror the meta CSP, and both can run a same-origin edge relay for supported functionality (a Claude proxy lives at api/claude-proxy.ts for Vercel and functions/api/claude-proxy.ts for Cloudflare, sharing one core module). Those are materially different deployment guarantees, even when users see the same React interface. The right documentation does not flatten that distinction. It names it. Storage is an authority decision, not a convenience API The PWA's live project path uses browser storage. The desktop path uses filesystem-backed stores under application data. Both are local. They are not the same. Browser persistence is governed by the browser's origin, quota, eviction behavior, and storage APIs. Desktop persistence is governed by filesystem access, native process boundaries, and the application's own read/write rules. That difference becomes especially important for security language. Browser/PWA protected IndexedDB data can use the application's passphrase-based encryption lifecycle when configured. The filesystem-backed desktop project store currently does not receive that same at-rest encryption. A UI toggle with the same name is not enough to make the protection equivalent. The actual persistence path decides what is protected. Native networking changes what "local server" means A browser connecting to localhost is still subject to browser rules such as CORS and Private Network Access. A Tauri desktop application can use an admitted native HTTP capability for local or cloud endpoints. That does not mean desktop networking is automatically safer. It means its policy must be defined and enforced differently — and "narrowly admitted" is meant literally here. The desktop shell's HTTP capability is an explicit allowlist, not an open pipe: // src-tauri/capabilities/default.json (excerpt) { "identifier": "http:default", "allow": [ "http://localhost:*/*", "http://127.0.0.1:*/*", "https://generativelanguage.googleapis.com/*", "https://api.openai.com/*" // …remaining provider hosts, nothing else ] } Enter fullscreen mode Exit fullscreen mode At runtime, the fetch adapter picks its implementation by environment: in the Tauri runtime it dynamically loads the native HTTP plugin; everywhere else it uses the browser's fetch. For WorldScript, that desktop-native path supports local inference-server workflows such as Ollama-compatible endpoints without requiring the WebView to bypass browser-origin rules. The browser/PWA path should not silently probe local ports or pretend that the same route will work without user-managed server configuration. The general lesson is simple: Browser security restrictions are product constraints, not annoyances to work around. Native capabilities should be narrowly admitted, not made globally available. UI copy must say when a feature is desktop-only or depends on local server configuration. PWA caching must not leak into desktop behavior A service worker is a powerful browser feature, but it is not a universal application runtime. WorldScript's service worker caches its web shell and handles offline fallbacks on web surfaces. In Tauri, the registration code takes the opposite path — it actively tears the browser mechanism down: // register-sw.ts (excerpt — called only from the Tauri branch) async function teardownServiceWorkerInTauri(): Promise { if (!('serviceWorker' in navigator)) return; const registrations = await navigator.serviceWorker.getRegistrations(); await Promise.all(registrations.map((reg) => reg.unregister())); const keys = await caches.keys(); await Promise.all( keys.filter(isWorldScriptOwnedCacheName).map((k) => caches.delete(k)), ); } Enter fullscreen mode Exit fullscreen mode It unregisters any existing service worker and purges the app's own caches. That prevents a stale browser cache from serving an offline fallback over the real bundled desktop application. This is a subtle example of platform adaptation done well: the feature is not merely disabled because it is inconvenient. It is disabled because its browser lifecycle would be the wrong authority for a native bundle. A cross-platform checklist Before claiming that a web and desktop product are "the same app," ask: Where does each platform persist the authoritative project? Which platform controls headers, CSP delivery, and network policy? Is offline behavior provided by a cached shell, a native bundle, or both? Which integrations need browser permissions, CORS configuration, or native capabilities? Does each storage path have the same encryption and recovery properties? Are platform-specific boundaries visible in the UI and documentation? A shared codebase is an implementation advantage. It is not a reason to erase the differences users and maintainers need to understand. The goal is parity where the product contract is shared—and honesty where the platform changes the contract. Source note: WorldScript Studio is open source (github.com/qnbs/WorldScript-Studio). Code references correspond to main at 2d9157c0 (2026-09-28); release anchor v1.28.8. Key files: register-sw.ts, index.html, vercel.json, docs/DEPLOYMENT.md, src-tauri/capabilities/default.json, services/ai/fetchAdapter.ts, api/claude-proxy.ts, functions/api/claude-proxy.ts. Part of the "Engineering WorldScript Studio" series. AI disclosure: AI tools helped with repository research, structure, and editing of this article. I reviewed the technical claims against the referenced source files before publication.

来源报道 · 1 篇 · 以下链接均前往原始媒体

← 返回精选动态 原文

更多内容