今天苏米要分享一个让我眼前一亮的方向:TypeScript 不再只是配合浏览器、Node 来跑前端或跨端,而是被一个叫 Perry 的新项目,直接“编译”成原生 App。
没有 Node、没有浏览器壳、更不用 Electron。简单说,TypeScript 第一次认真尝试做一门能“产出原生程序”的语言。

跨平台开发,其实一直在“绕路”
这几年跨平台方案很多,但大多是在“脚本世界”和“系统世界”之间搭桥,取舍明显:
Electron:简单,但代价很重
本质是把 Web 技术塞进桌面:JS → Chromium → 应用。
- 优点:开发快、生态全、上手友好。
- 缺点:占内存、启动慢、包体积大,界面质感也更像网页。

React Native:接近原生,但有成本
路线是桥接:JS → Bridge → Native UI。
- 优点:渲染原生组件,交互质感更正。
- 痛点:JS 与原生频繁通信,复杂交互下容易遇到性能、状态同步的问题;升级与原生依赖管理也要心智投入。

Flutter:体验稳定,但路线不一样
直接自己画 UI:Dart → Skia → GPU。
- 优点:一致性强,性能稳定,所见即所得。
- 代价:自带一套 UI 世界,与系统原生控件是两套体系;包体积、平台特性适配、平台无障碍和系统外观跟随要额外处理。
这些方案的共同点:让“脚本语言”尽量去适配“原生环境”。而 Perry 选择了另一条路。

Perry 在做什么?
Perry 把问题反过来问:为什么一定要“运行” TypeScript?能不能直接“编译”?

它的基本流程是:
TypeScript
↓
SWC 解析(TS → 更底层表示)
↓
LLVM
↓
Native Binary(二进制可执行文件)
产物是一个真正的本地可执行文件,意味着:
- 几乎无启动延迟,不再拉一个浏览器内核
- 不需要额外运行时环境(项目宣言:No runtime. No Electron. Just native binaries.)
- 发布就是一个二进制,更像 Rust/Go 的交付方式
更重要的是:UI、系统能力、事件循环等,都在编译期决定,运行起来就是“纯原生形态”。这和“边跑边桥接”的模式很不一样。

需要提醒的是,这类方案通常会从 TypeScript 的一个子集起步:动态特性(如 eval、部分反射、元编程)可能受限,NPM 生态也不是装了就能用,具体以项目文档为准。此外,调试、热重载、增量编译、跨平台链接器细节,都会逐步完善。
如何快速上手(5 分钟跑起来)
最快路径(确保先装好系统编译工具,见下一节):
- 安装 Perry
npm install @perryts/perry
- 写一个最简单的 TypeScript
// hello.ts
console.log("Hello Perry");
- 编译并运行
npx perry compile hello.ts -o hello
./hello
此时你得到的就是一个原生可执行文件。如果不想安装,直接一次性跑:
npx -y @perryts/perry compile hello.ts -o hello
小提示:
- 首次使用建议在空目录里实验,避免工具链冲突
- 若编译报错,多半是缺编译器或环境变量(见下一节)
- 可用系统命令验证产物(如 macOS/Linux 用
file ./hello查看架构)
环境要求(很容易踩坑)
Perry 依赖系统的本地编译工具链:
- macOS:安装 Xcode Command Line Tools
执行:xcode-select --install - Linux:安装 gcc/clang 及构建工具
例如 Debian/Ubuntu:sudo apt-get install build-essential clang - Windows:安装 Visual Studio Build Tools(含 MSVC、Windows SDK)
安装后在“x64 Native Tools Command Prompt for VS”里编译更稳妥
常见问题:
- PATH 未生效:重启终端或用对应的开发者命令行
- 跨平台编译:优先在目标系统本地编译;跨平台交叉编译需额外配置
- 杀毒/签名:macOS 需签名/隔离设置,Windows 可能被 Defender 拦截,按平台规范处理
它怎么做跨平台?

很多人会问:“UI 怎么办?”Perry 的做法很直接——用各平台的原生 UI:
- macOS → AppKit
- Windows → Win32
- Linux → GTK
- iOS / Android → 各自原生框架
例如写一段:
App({
title: "My App",
body: Text("Hello")
})
在不同系统上,会在编译期变成不同实现:
- macOS → NSWindow、NSTextField
- Windows → HWND、系统控件
- Linux → GTK 组件
关键点:这些转换发生在编译期,而不是运行时。所以程序跑起来时,已经是各平台的原生控件,启动轻、占用低、系统级无障碍与输入法等也更容易融入。
当然,使用原生控件意味着:
- 不同平台外观、尺寸、布局规范各不相同,需要写适配
- 统一风格要靠设计系统与组件封装,而不是“自绘一致性”
- 移动端需要考虑打包、签名、应用商店规范
它和 RN / Flutter 的关系
很多文章喜欢把它们放一起对比,但定位其实不在同一层:
- RN / Flutter 更像“UI 框架”
- Perry 更像“语言 + 编译器”
可以这样理解:
- RN:用 JS 控制原生(运行时桥接)
- Flutter:自己画 UI(渲染一致)
- Perry:直接生成原生程序(编译期决定一切)
选型建议(粗略经验):
- 优先追求启动速度、内存占用、系统感知强、包体更小 → 关注 Perry
- 要跨平台一致的 UI、成熟生态与插件、热更新/动态化 → Flutter/RN 更即插即用
- 已有大量 Web 代码、团队更熟前端栈 → Electron/RN 的迁移成本更低
当前阶段,Perry 更像 Rust/Go 的工程化体验在 TS 世界的投射,而不是一个“大而全”的 UI 框架。
写在最后
Perry 做了一件很有野心的事:把 TypeScript 从“需要运行环境的语言”,往“可以直接生成程序的语言”方向推进了一步。对独立开发者来说,这意味着你可以用更熟悉的语法,拿到更接近原生工程的产物。
现实建议:
- 早期尝鲜为主,评估功能覆盖和生态可用性
- 做小工具、系统级面板、启动器、原生壳子是很适合的切入点
- 关注调试、日志、崩溃上报、升级分发等工程环节的配套
如果你对跨平台开发感兴趣,值得一试!
Perry 官网:https://www.perryts.com/zh-Hans/
Github 地址:https://github.com/PerryTS/perry