根据用户实际下载的内容选择 JavaScript GUI 技术栈
了解为什么桌面外壳与组件库属于不同的层次,以及如何根据打包体积来选择 Electron、Tauri、MUI、shadcn/ui 等框架。
搜索“JavaScript GUI工具包”时,往往会出现将Electron与Material UI并列的列表,仿佛它们是竞争对手。但实际上并非如此:前者能提供可安装的窗口,后者则提供可用于该窗口的按钮,而大多数实际产品都需要两者之一。本指南将这两者区分开来,逐一介绍各自的主要选项,并对二者提出同一个决定性问题:最终会有多少代码出现在用户的机器上,以及其中有多少是真正必要的?
其他语言将两者合并在一起的结构
在Qt、GTK或WinForms这样的生态系统中,GUI工具包会一次性完成所有工作:它既打开原生窗口,又提供窗口内的控件。而JavaScript则将这一职责分配给两种不同的工具,正是这种混淆导致了大多数对比的混乱。
- 桌面外壳会将网页代码打包为可安装的应用程序。它们提供的是应用框架:原生窗口、系统托盘集成、对本地文件的访问以及安装程序。小部件并不包含在内。
- 组件库则提供各种交互元素,如按钮、表格、日期选择器和对话框。这些组件在浏览器中运行,无论该浏览器是嵌入在桌面应用中还是普通的网页标签页中,它们都能正常工作。
桌面产品可能会将 Tauri 与 MUI 结合使用;而网页产品则可能仅使用 MUI。选择外壳和选择组件库是两个独立的决策。
真正决定选项差异的关键问题
在某些生态系统中,许可协议是决定性因素,因为不恰当的约束可能会迫使你将产品开源。在 JavaScript GUI 领域,几乎所有项目都采用 MIT 许可证,因此许可协议很少会限制选择范围。真正能缩小选择范围的其实是文件大小。对于外壳类程序,区别在于安装包只有几兆字节还是几百兆字节;而对于组件库,则在于是交付整个设计系统,还是仅交付实际使用的少数几个组件。在阅读下文时,请始终牢记这一点。
此处列出的版本号反映的是撰写本文时的 npm 状态;在实际使用前请务必核对注册表中的信息。如需更深入地了解桌面端相关内容,包括最新的运行时环境,请参阅我们关于 Electron、Tauri、Electrobun 和 Deno 桌面框架的对比文章。
桌面壳层
Electron:经过验证的默认选择,自带浏览器
Electron(撰写本文时版本为 44.3.0,采用 MIT 许可协议)被列为开发依赖项:
npm install --save-dev electron
它将完整的 Chromium 浏览器与 Node.js 运行时一同打包到你的应用程序中。前端为网页形式,后端则基于 Node。其最大的优势在于成熟度:VS Code、Slack、Discord、Figma 和 1Password 都是基于该技术构建的,而且打包、自动更新、代码签名和崩溃报告等功能都有完善的工具支持,许多团队都已熟悉这些工具。
第二个优势是一致的渲染效果。由于直接使用浏览器,该应用在 Windows、macOS 和 Linux 系统上的显示效果完全相同,而且只需针对一个 Chromium 版本进行测试,无需处理三种不同系统的网页视图。此外,整个应用都是基于 JavaScript 开发的,因此任何前端开发人员都能参与主进程的开发工作。
其代价在于每个应用都自带浏览器。这些应用程序的体积通常在80到200 MB之间,由于每个Electron应用都会启动一个独立的Chromium实例,因此对于同时运行多个此类应用的用户而言,内存消耗会迅速增加。此外,更新这些内置的Chromium版本也是你的责任,需按照你自己的时间表来处理。
Tauri:系统级网页视图加上Rust后端
Tauri(撰写本文时版本为2.11.4,采用Apache-2.0和MIT双重许可)拥有专用的创建命令:
npm create tauri-app@latest
Tauri 并未自行打包浏览器,而是使用操作系统已提供的网页视图组件,其后台代码也用 Rust 编写而非 Node。两者大小差异源于架构设计而非其他因素:通常数据显示 Tauri 的打包体积在 3 到 10 MB 左右,而 Electron 的则在 120 到 200 MB 之间,内存使用量低 50% 至 75%,启动速度也更快。由于这种差异源自架构设计而非优化调整,因此在各版本中都保持不变。
安全模型也有所不同。在 Electron 中,除非进行严格限制,否则前端 JavaScript 可以通过 Node 访问操作系统。而在 Tauri 中,前端初始时没有系统访问权限;需要特殊权限的操作是由前端通过名称调用的 Rust 函数,此外 Tauri v2 还引入了能力系统,用于控制每个窗口可以调用哪些 API。Tauri 2 还支持 iOS 和 Android 平台,这是 Electron 完全不具备的,对于希望实现桌面端与移动端统一代码库的团队来说非常重要。
其缺点确实存在。各个平台的网页视图渲染方式略有不同,因此你现在实际上是在测试三种引擎而非一种。任何超出前端功能的需求都需要用到 Rust 语言。在 Windows 系统上,Tauri 依赖 WebView2,几乎所有现代系统都已预装该组件,但偶尔仍需要启动程序。一个合理的准则是:如果包大小尚未成为客户投诉的问题,仅仅为了节省几兆字节而选择 Tauri 就属于过早优化。只有当需要紧凑的安装包、较低的内存占用、更严格的隔离机制或移动端构建成为实际需求时,才应考虑使用它。
NW.js:较老的 Chromium 打包工具
NW.js(撰写本文时版本为 0.115.0,采用 MIT 许可协议)可作为普通软件包进行安装:
npm install nw
它还集成了Chromium,实际上出现的时间早于Electron。它的独特之处在于Node与DOM共享同一个上下文,因此网页可以直接调用Node API,无需像Electron那样区分主进程和渲染进程。对于某些应用而言,这样更易于理解。但相应的代价是社区规模小得多:学习资料较少,打包工具也较少,遇到问题时得到的帮助也更少,而且其包体大小仍与Electron相当。
Neutralino:最小的封装方案
Neutralino(撰写本文时版本为CLI v11.7.2,采用MIT许可证)是由全局安装的CLI驱动的:
npm install -g @neutralinojs/neu
这是一种轻量级的原生二进制文件,围绕系统内置的网页视图运行,不依赖 Node 也不依赖 Chromium。其包体大小通常在 1 到 5 MB 之间,由于涉及的框架更少,甚至比 Tauri 还要小。如果你的需求仅仅是封装现有的网页界面、添加系统托盘图标以及实现简单的数据持久化与有限级的文件访问功能,Neutralino 是实现这些目标所需架构最简的方案。在这四种框架中,它的生态系统最小,原生功能也最为有限,因此应将其视为实用工具框架,而非用于开发复杂应用程序的平台。
组件库
这一类别中的所有功能都在浏览器中运行,因此无论在桌面外壳环境中还是普通标签页中,各选项的表现都相当出色。此时,影响性能的因素从安装包大小转变为你的应用包会携带多少库代码。
MUI:覆盖范围最广,默认采用 Material 设计风格
MUI(撰写本文时版本为9.4.0,采用MIT许可证)会与其Emotion样式引擎一同安装:
npm install @mui/material @emotion/react @emotion/styled
在React组件库中,它是规模最大且历史最悠久的之一,遵循谷歌的Material Design设计规范。其组件覆盖范围极广,文档质量优异,而且其数据网格能够处理海量数据。如果你需要某个组件,MUI几乎肯定有,而且肯定已经有人问过关于它的相同问题。
不过它也是一个相当庞大的库。全新安装后在node_modules目录中的大小约为19 MB;这并非最终呈现给用户的体积,但足以体现其规模。你发布的打包文件依赖于有效的树摇剪技术,除非你对主题定制进行投资,否则所有内容都会呈现为Material Design风格,这种风格有些团队喜欢,而另一些团队则认为它过于受限。
shadcn/ui:直接复制源代码而非添加依赖
shadcn/ui(撰写本文时 CLI 版本为 4.21.0,采用 MIT 许可协议)并非需要导入的包。其 CLI 会先创建项目,再将各个组件复制到项目中:
npx shadcn@latest init
npx shadcn@latest add button dialog
每个组件都将 Radix UI 的基础元素与 Tailwind 样式结合在一起,CLI 运行完成后,这些内容就只是存储在仓库中的源代码。如果某个按钮需要不同的行为,只需直接编辑该按钮即可;无需处理任何封装组件、主题相关 API,也无需说服维护者。此外这种方式还能保证构建结果的纯净:只需添加四个组件,最终构建产物中也只会包含这四个组件。
使用该框架的代价在于维护工作。任何npm update操作都无法提升组件的性能;升级意味着需要手动复制代码并协调各项变更。此外它还依赖Tailwind,因此不适合不使用该框架的项目。这种设计模式通过扭转便捷性与定制化之间的常规权衡来发挥作用:你既能获得扎实的起点和完全的控制权,但相应地更新工作则由你自己负责。
Ant Design:专为密集的企业级界面设计
Ant Design(撰写本文时版本为6.6.3,采用MIT许可证)源自阿里巴巴,以单个包的形式进行安装:
npm install antd
它为数据量较大的业务界面提供了最完整的组件集:高级表格、复杂表单、传输列表、树形选择器。对于管理控制台和内部工具而言,你需要的组件很可能已经存在。该库也是此列表中体积最大的,安装后在磁盘上约占61 MB,大约是MUI的三倍;而且其鲜明的视觉风格比Material的设计更难摆脱。
Mantine:优秀的默认设置,无过度设计
Mantine(撰写本文时版本为9.6.1,采用MIT许可证)将其核心组件与hooks包分开:
npm install @mantine/core @mantine/hooks
那些认为MUI过于固执、而shadcn/ui过于繁琐的团队常常会选择这个方案。它拥有庞大的组件库、合理的默认设置、简单的主题定制功能、强大的TypeScript支持,还能无需额外配置即可实现出色的深色模式。即便单独来看,其hooks包也很有用,其中包含了用于检测点击外部区域、操作本地存储以及处理媒体查询的实用工具。它的社区规模小于MUI和Ant Design,因此第三方扩展较少,现成的解决方案也相对有限。
Radix UI与Headless UI:无样式功能实现
Radix UI(撰写本文时版本为1.1.23)和Headless UI(版本为2.2.10)均采用MIT许可证,可以分别按单个元素安装或作为一个整体包进行安装:
npm install @radix-ui/react-dialog
npm install @headlessui/react
这些是未加样式的基础组件。它们负责处理行为逻辑、键盘导航、焦点管理以及无障碍功能,所有的视觉设计则由你自行决定。这种分工很有价值,因为实现无障碍的组件其实比看上去要复杂得多。一个合格的对话框在打开时必须保持焦点在内,关闭时再将焦点恢复,按 Esc 键即可关闭,并且要能被辅助技术正确识别;一个合格的下拉菜单需要支持箭头键导航、通过输入选择内容,同时还应合理地放置在视口边缘附近。大多数团队都低估了这些工作量,最终交付出存在隐性缺陷的产品。
Radix 是 shadcn/ui 所依赖的基础框架,而 Headless UI 则由 Tailwind 团队维护。显而易见的代价就是你需要自己编写所有的样式代码,这正是其设计初衷,但依然是一项实际的工作。
PrimeReact:为特殊组件提供广泛的支持
PrimeReact(撰写本文时版本为11.1.0)属于PrimeFaces系列,该系列还包括Angular、Vue和Java:
npm install primereact
它提供的功能极为丰富,从图表和组织结构图到树形表格、调度器、上传组件以及一整套输入控件,其中许多功能是其他库完全不具备的。当你需要一些特殊功能时,首先应该在这里查看。在决定使用之前,请自行确认其许可协议。它的npm元数据中指向的是一个许可文件(“SEE LICENSE IN LICENSE.md”),而非SPDX标识符,而且该供应商除了提供免费版本外,还出售付费主题和模板。核心库是开源的,但在基于它开发商业产品之前,请务必仔细阅读实际条款。
另外三个值得关注的库
- Chakra UI(v3.37.0,MIT许可证)将无障碍性置于首位,并通过属性来设置组件样式;它的定位介于MUI的全面解决方案与Radix的原始基础组件之间。
- daisyUI(v5.7.34,MIT许可证)是一个Tailwind插件,提供组件类而非React组件,因此也可用于Svelte、Vue或静态标记语言。
- HeroUI(v3.2.4,MIT许可证)是NextUI的更名后的继任者,它将Tailwind与React Aria结合在了一起。
快速决策指南
对于桌面应用框架:
- 如果需要成熟的生态系统、一致的渲染效果以及仅依赖JavaScript的团队,可选择Electron。
- 如果需要较小的下载体积、较低的内存占用、更严格的安全机制或面向移动端,可选择Tauri。
- 为现有网页界面添加一层轻量封装即可实现 Neutralino 的功能。
- 若希望将 Node 与 DOM 放入同一共享上下文,则适合使用 NW.js。
至于组件库:
- 如果需要几乎所有的组件以及完善的文档,那么 MUI 是最佳选择。
- 若想在 Tailwind 项目中自主修改代码,shadcn/ui 是合适的选择。
- 面对密集的企业级数据界面时,Ant Design 更为适用。
- 需要简洁且无过多主观设计的方案,Mantine 是不错选择。
- 若需要自带无障碍功能的自定义设计系统,Radix 或 Headless UI 更为合适。
- 面对特殊用途的组件,PrimeReact 是理想选择。
有一条规则可以覆盖所有建议:如果您的团队已经熟练掌握其中某款工具,那么这种专业能力几乎总能胜过其他稍好一些的选项。
总结
在这两层技术中,功能列表已基本趋于一致;这些项目有数年时间可以互相借鉴优秀的理念。但在权重分配方面,它们仍存在让用户能感受到的差异。Electron与Tauri则让整个应用面临权重选择的问题:是打包浏览器以确保稳定性,还是使用操作系统提供的浏览器从而让打包体积缩小二十倍甚至更多。在MUI与shadcn/ui之间做选择,则是将这种权衡应用到组件层面:是依赖他人维护的完整设计系统,还是仅获取所需组件并自行维护。在开始比较功能列表之前,先确定您的产品倾向于哪一种权衡方式,这样候选方案通常就能自行显现。