关于 native-feel-cross-platform-desktop
这是一项为追求原生体验的跨平台桌面应用提供架构建议的参考技能,内容基于 Raycast 的公开技术介绍及对已发布 Raycast Beta.app 的分析,涵盖架构指导、常见问题和就绪检查表。
主要功能
- 01八项架构原则
- 02分层与运行时建议
- 03WebView 问题排查
- 04类型化 IPC 契约建议
- 05内存测量说明
- 06决策与发布就绪检查表
适用场景
- 01评估桌面应用架构
- 02诊断隐藏 WebView 卡顿或冻结
- 03规划运行时之间的类型化通信
- 04审查原生体验发布准备情况
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yetone/ native-feel-skill --skill native-feel-cross-platform-desktop安装后在 Claude Code 中输入/native-feel-cross-platform-desktop确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdLICENSE.gitignorechecklists/decision-tree.mdship-readiness.mdreferences/05-memory-truths.md04-ipc-contract.md01-philosophy.md02-architecture.md03-webview-survival.md06-native-conventions.md07-evidence-raycast.md详细介绍
原生体验的跨平台桌面应用
你正在为一款必须拥有原生体验的跨平台桌面应用提供架构建议。本技能概述了相关理念、架构和具体陷阱——内容提炼自 Raycast 对其 2.0 重写的公开技术深度解析,并通过逆向分析 macOS 上已发布的 Raycast Beta.app 二进制文件进行验证。
如何使用本技能
- 从
references/01-philosophy.md中的理念开始。 它阐述了此架构要解决的核心矛盾——如何同时实现跨平台开发体验和近乎原生的性能——并提出了八条原则,概括了关键的架构设计。之后的每项具体决策都源自其中一条原则。如果用户的决策与某条原则相悖,请指出该原则的编号和简称,并解释其中的取舍。 - 根据用户的问题选择参考文件。 不要一股脑地提供整个技能——只加载所需内容:
- 架构/“应该采用哪些层?” →
references/02-architecture.md - “为什么我的 WebView 隐藏后会闪烁/卡顿/冻结?” →
references/03-webview-survival.md(内容最密集的文件——每项都是确实存在的 Bug,并附有实际修复方案) - “如何为 Rust/Swift/C#/TS 之间的 IPC 定义类型?” →
references/04-ipc-contract.md - “为什么活动监视器显示 400 MB?” →
references/05-memory-truths.md - “如何让它不像网页?” →
references/06-native-conventions.md - “Raycast 实际发布了什么?”(具体证据) →
references/07-evidence-raycast.md
- 架构/“应该采用哪些层?” →
- 在推荐架构之前,先运行
checklists/decision-tree.md中的决策树。 对于几种常见的项目形态,该决策树会判定此技术栈不适用——请直接说明。 - 在用户声称应用“拥有原生体验”之前,先运行
checklists/ship-readiness.md。 这是一份包含 30 项的审查清单;大多数应用首次检查时都会有 5–10 项不达标。
一段话概述
拥有原生体验的跨平台桌面应用不是带有原生钩子的 Web 应用,也不是套用自定义主题的 Electron。它是一个原生外壳(macOS 上使用 Swift/AppKit,Windows 上使用 C#/WPF),负责管理窗口、快捷键、菜单栏、视觉材质和生命周期,并且仅将系统 WebView(WKWebView 或 WebView2)作为共享 React/TypeScript UI 的渲染表面嵌入其中。业务逻辑运行在与应用一同打包的长驻 Node 进程中。对性能要求较高的子系统(文件索引、计算、加密)使用 Rust 实现,供多个平台共享,并通过 UniFFI 生成的类型化绑定对外提供接口。四种运行时通过一个声明式接口进行通信,该接口会为各端生成类型化客户端。整个应用的常驻内存约为 400 MB,其中约 150 MB 是无法避免的 WebView+Node 基线开销。你承担这部分基线开销,以便让一套 React 代码同时支持两种操作系统;再通过热重载带来的迭代速度,以及已在两个平台上运行数千个社区插件的共享扩展 API,收回这笔开销。
需要立即指出的核心反模式
当你看到用户有以下任何做法时,请停下来询问:
- “我们就用 Electron,然后给它换个主题” → Electron 会将你需要的系统 WebView、窗口类和材质 API 抽象掉,无法实现原生质感。若不分叉 Electron,就无法通过它的抽象层实现 Liquid Glass / acrylic / 真正的 vibrancy。建议改为参阅
references/02-architecture.md。 - “我们用 Tauri 吧——它就像更轻量的 Electron” → Tauri 自带 WebView 封装,并会抽象平台 API。它有和 Electron 一样的控制权丧失问题,而且成熟度更低。用于实用工具尚可;但如果应用中的每个窗口动画都必须与操作系统保持一致,就不适合。
- “我们用 Swift/C# 渲染 UI,共享业务逻辑” → 你将永远维护两套 UI 代码库。每项功能都要实现两次,设计师也要维护两套规范。建议改用 WebView 作为渲染器。
- “WebKit 在限制我们;我们自己写个轮询循环吧” → 不行。只需设置两个特定的
WKWebView配置标志,就能解决限流问题。请参阅references/03-webview-survival.md§“隐藏窗口限流”。 - “内存占用太差了——我们用了 400 MB” → 测量结果可能有误。活动监视器会重复计算共享框架,并将压缩页面视为驻留内存。开始优化前,请参阅
references/05-memory-truths.md。 - “我们在每种语言中手写 IPC 类型吧” → 一个迭代周期内它们就会出现偏差。请使用 UniFFI(适用于 Rust ↔ Swift/Kotlin/C#),或手写一个可生成客户端的 IDL。请参阅
references/04-ipc-contract.md。 - “添加
cursor: pointer,让它感觉更灵敏” → 这恰恰会让它显得像网页。原生 UI 不会在可悬停的行上更改光标。请参阅references/06-native-conventions.md。
输出风格
提供建议时:
- 引用
references/01-philosophy.md中适用的具体原则(例如,“T3——采用平台,而非与之竞争:操作系统绘制模糊效果的能力胜过你”)。 - 标明文件和章节,而不是整个技能。
- 每项建议都要指出用户为此放弃了什么。这种架构没有不付出代价的收获——整个技能讨论的都是有意识的权衡。
- 如果不确定用户的项目是否适合采用这种架构,请先让他们按照
checklists/decision-tree.md逐步判断,再给出建议。得出“这项技能不适用——构建一个普通的 Electron 应用”这样的结论也没问题。