Logo
热心市民王先生

重构解决的核心问题

Raycast 2.0 的重构并非为了技术而技术,而是为了解决 v1 架构下日益突出的四个核心问题。本章深入分析每个问题及其解决方案。

问题一:Windows 跨平台支持

问题背景

Windows 支持从一开始就是 Raycast 的长期愿景:

“It was always the plan, from day one, but in the early days we wanted to focus on a single platform and nail the experience there before even considering expanding.”

(从第一天起这就是计划,但早期我们想先专注于单一平台,把体验做到极致,然后再考虑扩展。)

2023 年底启动 Windows 版本开发时,面临的现实是:v1 是纯 Swift + AppKit 的 macOS 原生应用,无法直接移植。

解决方案:共享 Web 技术栈

v2 架构通过以下设计实现 Windows 支持:

flowchart TB
    subgraph "Shared Code (95%+)"
        A[React Frontend]
        B[Node Backend]
        C[Rust Core]
    end
    
    subgraph "Platform Specific (5%)"
        D[Swift + AppKit<br/>macOS Host]
        E[C# + WPF<br/>Windows Host]
    end
    
    D --> A
    E --> A
    A <-->|IPC| B
    B <-->|FFI| C

关键设计决策:

  • Web Frontend:单一代码库同时构建 macOS 和 Windows 版本
  • Node Backend:业务逻辑在两个平台上 100% 共享
  • Rust Core:数据层和同步引擎跨平台共享

开发效率提升

“Most product work happens in the shared web frontend and Node backend. When we ship a feature, it works on macOS and Windows.”

(大部分产品工作在共享的 Web 前端和 Node 后端完成。当我们发布功能时,它在 macOS 和 Windows 上都可用。)

这意味着:

  • 功能开发成本从 “2x”(两套 Native 实现)降低到 “1x + 增量”(一套实现 + 平台适配层)
  • 产品团队无需关心目标平台,专注于功能本身
  • 发布节奏在两个平台间保持一致

问题二:开发迭代速度

v1 的痛点

纯 Native 开发的最大痛点是开发循环时间长

“Hot reloading means UI changes show up in under a second, compared to recompiling the Swift target and restarting the app in v1.”

(热重载意味着 UI 更改在一秒内显示,相比之下 v1 需要重新编译 Swift 目标并重启应用。)

v1 开发循环时间对比:

环节v1 (Swift/Native)v2 (React/Web)提升倍数
代码修改 → 看到结果分钟级(编译+重启)秒级(热重载)10-60x
UI 调试迭代缓慢即时数量级提升
功能原型验证小时级分钟级10x+

解决方案:Web 技术栈的成熟生态

React + TypeScript + Node.js 的开发体验优势:

  1. 热重载(Hot Reloading)

    • 代码更改后自动刷新,保留应用状态
    • 无需等待编译,立即看到效果
  2. 丰富的调试工具

    • Chrome DevTools 的成熟生态
    • React DevTools 组件调试
    • Network、Performance 面板
  3. 成熟的构建工具

    • Vite/Webpack 的快速构建
    • TypeScript 的类型安全
    • ESLint/Prettier 的代码规范

业务价值转化

开发速度的提升直接转化为产品价值:

“We can prototype, iterate, and fix bugs significantly faster. This benefits users directly – features ship sooner, and fixes land quicker.”

(我们可以显著更快地进行原型设计、迭代和修复 bug。这直接让用户受益——功能更快发布,修复更快落地。)

量化影响(估算):

  • 新功能从设计到发布的周期缩短 30-50%
  • Bug 修复的平均响应时间从 “下个版本” 缩短到 “当天/当周”
  • 实验性功能可以更快验证,降低试错成本

问题三:文件搜索性能

v1 的限制

v1 的文件搜索依赖 macOS 的 Spotlight 元数据索引:

“In v1, file search relied on Spotlight metadata. It (mostly) worked, but we were limited to what Spotlight had indexed, and it couldn’t work on Windows at all.”

(在 v1 中,文件搜索依赖 Spotlight 元数据。它(大部分时候)能工作,但我们受限于 Spotlight 已索引的内容,而且它在 Windows 上完全无法工作。)

Spotlight 依赖的问题:

  • 索引范围不可控(用户可能关闭某些目录的索引)
  • 索引延迟(新文件可能不会立即被搜索到)
  • Windows 上无对应方案

解决方案:Rust 实现的自定义文件索引器

v2 构建了一个从零开始的文件索引器,核心特性:

技术实现:

  • 语言:Rust(性能关键)
  • 架构:独立进程运行
  • 扫描方式:直接扫描文件系统
  • 更新机制:通过文件系统事件保持索引实时更新

Windows NTFS 优化:

“On Windows, walking the NTFS filesystem the normal way is too slow for the scan times we need. So we built a dedicated NTFS scanner that reads the Master File Table directly – the only practical way to index an entire drive in seconds rather than minutes.”

(在 Windows 上,以常规方式遍历 NTFS 文件系统对于我们的扫描时间需求来说太慢了。因此我们构建了一个专门的 NTFS 扫描器,直接读取主文件表——这是在数秒内而非数分钟内索引整个硬盘的唯一实用方法。)

Master File Table (MFT) 扫描原理:

flowchart LR
    A[常规扫描] --> B[逐个目录遍历]
    B --> C[stat 每个文件]
    C --> D[耗时: 数分钟]
    
    E[MFT 扫描] --> F[直接读取 NTFS MFT]
    F --> G[获取所有文件元数据]
    G --> H[耗时: 数秒]
    
    style A fill:#f8d7da
    style E fill:#d4edda

MFT 是 NTFS 文件系统的核心数据结构,包含所有文件和目录的元数据。直接读取 MFT 可以将全磁盘扫描时间从数分钟缩短到数秒。

Rust 的性能优势:

“The indexer is one of the places where Rust’s performance matters most. Scanning hundreds of thousands of files and building a search index needs to happen in the background without affecting the rest of the app. Predictable memory usage and no GC pauses make that possible.”

(索引器是 Rust 性能最重要的场景之一。扫描数十万文件并构建搜索索引需要在后台进行而不影响应用的其他部分。可预测的内存使用和没有 GC 暂停使这成为可能。)

特性Rust 实现其他语言 (Node/Python)
内存使用可预测,无 GCGC 可能导致不可预测暂停
性能接近 C/C++ 级别解释型/VM 开销
并发编译时保证线程安全运行时竞争风险
可靠性类型系统防止空指针/数据竞争需要更多测试覆盖

用户可见的改进

新的文件索引器带来的用户体验提升:

  1. 即时搜索:根搜索(Root search)现在包含完整的文件搜索
  2. 不依赖 Spotlight:无论用户如何配置系统索引,文件搜索始终可用
  3. 跨平台一致:macOS 和 Windows 使用相同的索引技术,体验一致
  4. 更快的搜索速度:基于自定义索引而非外部依赖

问题四:团队扩张能力

v1 的人才瓶颈

v1 的纯 Native 栈带来了人才招聘的挑战:

“Finding engineers who can work on React, TypeScript, and Node is much easier than finding engineers with deep AppKit experience.”

(找到能使用 React、TypeScript 和 Node 的工程师比找到有深度 AppKit 经验的工程师容易得多。)

市场供需对比(2023-2024 年估算):

技术栈市场人才供给平均薪资溢价
React/TypeScript/Node高(前端/全栈主流)基准
Swift + AppKit低(iOS/macOS 特定)+20-40%
C# + WPF中(企业应用常用)基准

解决方案:主流 Web 技术栈

转向 React + TypeScript + Node 栈带来的好处:

  1. 更大的候选池

    • 市场上 React 开发者数量级多于 AppKit 开发者
    • 更容易找到有 React Native、Web 应用经验的候选人
  2. 更低的入职门槛

    • 新团队成员可以更快上手
    • Web 开发知识更具可迁移性
  3. 更高的团队灵活性

    • 工程师可以在不同功能间流动
    • 不受特定平台技能限制

Native 工程师的角色转变

这并不意味着完全放弃 Native 工程师:

“This doesn’t mean we stopped needing native engineers – we still have dedicated Swift and C# engineers working on the host apps – but the majority of product work no longer requires specialized platform knowledge.”

(这并不意味着我们不再需要 Native 工程师——我们仍然有专职的 Swift 和 C# 工程师在开发 Host 应用——但大部分产品工作不再需要专门的特定平台知识。)

角色分布调整:

角色v1v2
产品工程师需要 Swift + AppKit需要 React + TypeScript
Native 工程师主导功能开发专注 Host 应用和底层集成
团队构成主要 Native主要 Web + 少量 Native

问题解决效果总结

问题v1 状态v2 解决方案效果
Windows 支持无法支持共享 Web 技术栈✅ macOS + Windows 双平台
开发速度编译慢Web 热重载✅ 数量级提升
文件搜索Spotlight 受限Rust 自定义索引器✅ 更快 + 跨平台 + 不依赖系统索引
团队扩张AppKit 人才稀缺主流 Web 栈✅ 更大的招聘池

重构的核心价值在于:移除了限制产品发展的架构天花板,同时保持了产品体验的底线要求