Dioxus 全栈框架解析:用一套 Rust 代码库构建 Web、桌面与移动端应用
【免费下载链接】dioxusFullstack app framework for web, desktop, and mobile.项目地址: https://gitcode.com/GitHub_Trending/di/dioxus
Dioxus 是一个以 Rust 为核心的全栈应用框架,目标是让开发者用同一套代码库同时覆盖 Web、桌面、移动端与服务器端。本文以仓库内 土耳其语 README 译本 为主线骨架,结合本仓库的源码与架构文档,系统讲解 Dioxus 的核心特性、信号式状态管理、热重载与打包工作流、平台支持矩阵,以及与 Tauri、Leptos、Yew、egui、Iced、Electron 等主流框架的定位差异。读完本文,你将掌握 Dioxus 的基本开发模型、CLI 的常用命令、多端打包思路,以及它区别于同类框架的关键设计取舍。
从一段最小示例认识 Dioxus
翻译文档在开篇给出了一段非常经典的“击掌计数器”(High-Five counter)示例,它是理解 Dioxus 三大设计要素的最佳入口:use_signal信号、rsx!UI 宏、以及事件闭包驱动的状态更新:
fn app() -> Element { let mut count = use_signal(|| 0); rsx! { h1 { "High-Five counter: {count}" } button { onclick: move |_| count += 1, "Up high!" } button { onclick: move |_| count -= 1, "Down low!" } } }这短短数行已经涵盖了 Dioxus 的全部核心机制:
use_signal(|| 0)创建一个信号(Signal),它承载可变状态并在读取处自动建立响应式订阅;- 在
rsx!内用 Rust 语法书写类 JSX 的 UI 树,{count}会在信号变化时自动刷新; - 事件处理器通过
move |_| ...闭包直接修改信号,无需手动“setState”再重新渲染整棵组件树。
把这段逻辑补全成可运行程序,只需像仓库中 hello_world.rs 一样加上入口函数:fn main() { dioxus::launch(app); }。launch会根据当前启用的渲染器特性(web、desktop 等)自动选择目标平台启动应用。仓库根目录的 Cargo.toml 将dioxus(伞形 crate,见 packages/dioxus)与dioxus-core、dioxus-rsx、dioxus-signals、各平台渲染器等组织在同一 workspace 中,也就是说用户侧一个dioxus依赖即可引入从虚拟 DOM 到 HTML 元素再到路由的完整能力。
⭐️ 独有特性:文档中反复强调的四个支点
翻译文档把 Dioxus 区别于其他框架的能力浓缩为以下几点,这些主张都能在本仓库找到对应的代码级落点:
- 几行代码完成跨平台应用:Web、桌面、移动、服务器等场景共享同一套 UI 代码,这是“Renderer-agnostic(渲染器无关)”架构的直接结果;
- 符合人体工学的状态管理:文档明确指出 Dioxus 的状态管理思路融合了 React、Solid 与 Svelte 三者的长处;
- 集成打包器:
dx bundle可把应用打包到 Web、macOS、Linux 与 Windows; - 真正的全栈能力:通过 Server Functions 在前后端间无缝复用类型与调用,配套 CLI 完成开发与发布全流程。
从 crate 依赖结构看(见 架构总览),这一设计被拆解为:dioxus-core负责虚拟 DOM 与调度、dioxus-signals+generational-box提供响应式状态、dioxus-rsx负责 UI 宏解析、而dioxus-web/dioxus-desktop/dioxus-ssr/dioxus-liveview/dioxus-native则各自实现同一套WriteMutations渲染协议,这也是“同一份组件代码到处运行”的底层原因。
即时热重载:dx serve一条命令的开发循环
文档用“Anında hot-reloading”(即时热重载)来描述 Dioxus 的开发体验:只需执行
dx serve应用即被启动,之后编辑 markup 与样式,改动会在毫秒级实时出现在界面上,无需手动重新编译。文档也坦率地指出,当时 Rust 代码本身的热更新能力“尚非一流”,通常需要借助 hot-lib-reloader 之类的第三方机制实现。
<图片:notes/hotreload.gif,alt="dx serve 实时热重载 UI 的演示截图" >不过要注意,图片说明不可这样直接拼进正文,下文统一用 Markdown 图片语法。
当前主仓库 README.md 已把这一能力推进到“亚秒级 Rust 热修补”:dx serve --hotpatch可在毫秒内热更新 Rust 代码,这与 架构文档 07-HOTRELOAD 描述的“两套互补系统”互相印证——RSX 模板字面量改动通过 WebSocket 增量下发,函数级热补丁则借助跳表间接寻址实现整段 Rust 函数的热替换;此外资源(CSS/图片等)也支持热重载。也就是说,翻译文档中“改样式实时可见”的承诺在今天已经升级为“连同 Rust 逻辑一起热更新”的完整开发循环。
打包器与产物体量:dx bundle背后的优化管线
文档将打包列为 Dioxus 的重要卖点:执行dx bundle,应用会以尽可能高的优化等级被编译并打包成可分发的产物。Web 端产物可享受.avif图片生成、.wasm压缩、代码 minify 等一系列优化;文档还给出两个量级参考——Web 应用可小于 50kb,桌面/移动端应用当时约为 15mb 以内。当前仓库主 README.md 更新为桌面/移动端应用小于 5mb,而平台表格中桌面端“便携二进制 <3mb”的描述则一直保留——这些数字来自官方文档而非基准测试,且随版本演进存在差异,实际体积取决于依赖与特性配置。
<图片:notes/bundle.gif,alt="dx bundle 打包命令行输出演示"打包与热重载的背后是统一入口dx,它来自 packages/cli。CLI 承担了创建(dx new)、开发(dx serve)、检查(dx check)与打包(dx bundle)等任务,并读取Dioxus.toml做平台化配置。以 packages/cli/README.md 中的最小配置为例:
[application] name = "project-name" # 当前支持平台:web, desktop default_platform = "web" # 可选:启用静态目录拷贝(例如 "public") public_dir = "public" [web.app] title = "Hello" [web.resource.dev]dx bundle的优化并不是“黑箱魔法”,而是依赖一套构建期协作:asset!()宏把资源元数据写进二进制,CLI 在构建期提取、处理资源并回填最终 URL(见 架构文档 08-ASSETS)。换句话说,你在代码里声明资源,由 dx 负责在产物层面替你完成压缩、优化与寻址。
状态管理:从信号到响应式模型的工程实现
翻译文档在特性列表中强调 Dioxus 的“Ergonomik durum yönetimi”(符合人体工学的状态管理),并特意对比提到 Dioxus 0.5 起借鉴了 Leptos 的Copy模型。仓库内的 04-SIGNALS 架构文档 展示了这套体系的分层实现:
- generational-box:用“代数”(generation)计数为引用提供
Copy语义。每次访问都会校验代际,若已被释放则返回BorrowError::Dropped,从而在没有运行时开销的前提下规避悬垂引用; - Signal<T>:核心可变响应式原语,
.read()订阅当前作用域,.peek()只读不订阅,.write()修改后对所有订阅者广播mark_dirty; - Memo / Resource / Store:分别承担派生值、异步资源与嵌套结构三种场景——Store 甚至能把响应式粒度细化到结构体字段级别。
use_signal的状态之所以在多次渲染之间“一直活着”,是因为它存储在组件作用域(scope)的堆上,组件树只持有Copy的轻量指针。仓库里 counters.rs 给出了把信号与Vec结合的完整写法:use_signal(|| vec![0, 0, 0])存储计数器列表,use_memo派生出总和,再通过counters.iter()与counters.write()[i] += 1做增删改,界面会随信号自动保持同步——这正是文档所述“用普通的 Rustfor循环与if也能保持响应式”的直接证据。
平台支持矩阵
翻译文档以表格形式完整列出了当时各平台的成熟度,本仓库的渲染器实现与之一一对应:
| 平台 | 支持级别 | 能力要点(原文表述) |
|---|---|---|
| Web | 1 级 | 基于 WebAssembly 直接渲染到 DOM;SSR 预渲染后客户端 rehydrate;“Hello World”约 50kb(与 React 同级);内置开发服务器与热重载 |
| Fullstack | 1 级 | Suspense、hydration、服务端渲染;Server Functions 提供内置后端;Extractors、middleware、路由集成;与移动/桌面端兼容 |
| 桌面 | 1 级 | 用 Webview(实验性可选 WGPU 或 Freya/Skia)渲染;cargo run或dx serve即可构建;无需 IPC 直连系统 API;支持 macOS、Linux、Windows,便携二进制 <3mb |
| Liveview | 1 级 | 应用(或单个组件)整体在服务端渲染;与 axum、warp 等 Rust 框架集成;官方文档称可支撑超 1 万并发连接并保持极低延迟 |
| 移动 | 2 级 | Webview(或实验性 WGPU/Skia)渲染;iOS 与 Android 支持;文档写明当时仍相当实验性,2024 年间持续演进 |
| 终端 | 2 级 | 类似 ink.js 直接渲染到终端;借鉴浏览器 flexbox/CSS 模型;内置文本输入、按钮与焦点系统等组件 |
对照当前主 README.md,平台矩阵已进一步更新为 Web、Desktop、Mobile、Server-side Rendering 四类,其中 SSR 新增了静态站点生成(SSG)与增量再生成能力,移动端则强调可直接调用 Java/Objective-C API、dx serve --platform android秒级上机运行。这说明文档中的“2 级支持”状态正处于快速升级通道中。
需要特别说明的是:表格中关于 Liveview“超 1 万并发与极低延迟”属于官方文档表述,仓库内没有可复现该数据的基准代码,引用时应视作产品定位而非实测结果。
如何运行仓库中的示例
翻译文档给出两种运行示例的方式:
- 直接使用 Cargo:
cargo run --example <示例名>; - 更推荐的方式是安装 dioxus-cli 后用
dx serve运行,因为多数示例同时支持 Web 平台;如需 Web 端,还要在Cargo.toml上调整特性,或关闭默认的 desktop 特性。
当前仓库把示例按主题归档在 examples 下的各目录中(如01-app-demos、02-building-ui、04-managing-state、07-fullstack等)。同时主 README.md 有一处重要提示:主分支示例面向的是 git 版本的 dioxus 与 CLI,若需要与最新稳定版匹配的示例应切换到对应稳定分支。使用 CLI 以 Web 平台运行示例的完整命令为:
dx serve --example <示例名> --platform web -- --no-default-features其中--no-default-features用于关闭默认桌面特性、改走 Web 目标——这正是文档提到的“Cargo.toml 特性调整”在命令行层面的等价表达。CLI 本身可通过cargo install dioxus-cli安装(参见 packages/cli/README.md),安装后dx --help可查看全部子命令。
Dioxus 与其他框架的对比
翻译文档用相当大的篇幅横向对比了六个代表性框架,并强调“我们热爱所有框架”——Dioxus 的许多组件(如 flexbox 布局库 Taffy)也被 Bevy、Zed、Lapce、Iced 等生态项目复用。以下按原文脉络逐一还原其论据。
与 Tauri:原生的差异与共享的 DNA
Tauri 面向桌面(并即将扩展移动端),前端使用 React/Vue/Svelte 等 Web 框架,需要 native 能力时再编写 Rust 函数并通过前端调用:
- Natively Rust:Tauri 的架构使开发者受限于 JavaScript/WebAssembly;Dioxus 的 Rust 代码直接运行在用户机器上,线程生成、文件系统访问无需经过 IPC 桥接;
- 目标不同:Tauri 必须兼容 JavaScript 及其复杂的构建工具链,这限制了它的能力边界;Dioxus 专注 Rust,因此能提供 Server Functions、高级打包与 native renderer 等额外特性;
- 共享 DNA:两者虽是不同项目,但在窗口(windowing)与 webview 层面共同使用了 tao、wry 等基础库。
与 Leptos:响应式模型与控制流的分野
Leptos 借鉴 SolidJS/SolidStart,擅长 fullstack Web;文档认为它与 Dioxus 在 Web 上目标相近,但存在数个关键差异:
- 响应式模型:Leptos 使用信号,Dioxus 使用虚拟 DOM + 重渲染;理论上信号更高效,但实践中 Dioxus 受 block-dom 启发的模板 diffing 让差距几乎可以忽略;
- 控制流:Leptos 把响应式绑定在
for、if等原语与<For>组件上,一旦写错可能丢失整个子树的响应性,难以调试;Dioxus 允许使用普通迭代器、Rustfor与if,界面仍保持响应式。文档用同一个“可增删计数器列表”需求做了对拍。Dioxus 侧(与仓库 counters.rs 同思路):
fn Counters() -> Element { let mut counters = use_signal(|| vec![0; initial_length]); rsx! { button { onclick: move |_| counters.push(counters.len()); "Add Counter" } ul { for idx in 0..counters.len() { li { button { onclick: move |_| counters[idx] += 1; "{counters[idx]}" } button { onclick: move |_| { counters.write().remove(idx); } "Remove" } } } } } }而 Leptos 一侧则要求手工管理 key 跟踪、创建新信号并在移除时手动释放内存,代码明显更冗长。文档还对比了 DSL:Dioxus 使用类 Rust 语法以享受 code folding 与语法高亮,并能自动做字符串拼接;Leptos 更贴近 HTML、期望用户配合format!/闭包使用:
// dioxus rsx! { div { class: "my-class", enabled: true, "Hello, {name}" } } // leptos view! { <div class="my-class" enabled={true}> "Hello " {move || name()} </div> }Copy状态:Dioxus 0.1~0.4 用 lifetime 变通 borrow checker,事件处理尚可、async 侧却棘手;0.5 起引入借鉴自 Leptos 的Copy模型(即仓库中的 generational-box crate),事件与异步代码都得到简化;- 目标差异:Dioxus 面向 Web、桌面、移动、Liveview 等多平台并维护社区 SDK,发布节奏因此慢于聚焦 Web 的 Leptos;后者拥有
<Suspense/>流式 HTML、islands、<Form/>等 Web 专属特性,纯 Web 应用的 footprint 通常更小。
与 Yew:为什么需要一个新的 Web 框架
Yew 启发了 Dioxus,但其架构无法满足 Dioxus 的诉求,最终促成了 Dioxus 的诞生:
- 单页 Web 专用:Yew 天生面向 SPA,因此被限定在 Web;Dioxus 因支持跨平台 fullstack,同样适合桌面、移动与服务器应用;
- 开发者工具:Dioxus 提供自动格式化、热重载与打包器等成套工具;
- 持续演进:文档称 Dioxus 保持活跃迭代,新特性与日常 bug 修复不断(0.5→0.7 的演进在本仓库 releases 目录中也有迹可循)。
与 egui:immediate 与 retained 的本质区别
egui 是 Rust 的跨平台即时模式(immediate mode)GUI 库,支撑着 Rerun.io 等项目:
- Immediate vs Retained:egui 每个 frame 都全量重绘,适合游戏类应用,但样式与布局不会在帧间保留;Dioxus 是 retained 模式 UI,界面一次性建立、在帧间按需更新,因而能使用 HTML/CSS 等原生 Web 技术,并获得更好的续航与性能表现;
- 可定制性:egui 自带样式与布局方案;Dioxus 内部使用 HTML/CSS,因此 Tailwind、Material UI 等任意 CSS 库都能直接套用;
- 状态管理:egui 围绕单一全局 state 对象;Dioxus 通过组件 + props 支持状态封装与复用。
与 Iced:Elm 架构与 native 质感
Iced 是受 Elm 启发的跨平台 GUI 库,通过 WGPU 提供 native 渲染并支持 DOM 节点式的 Web 输出:
- Elm 状态管理:Iced 采用 message/reducer 的 Elm 模型,与 Dioxus 截然不同且常常显得冗长;
- Native 观感:Dioxus 以 webview 为渲染器,天然具备系统原生文本框、复制粘贴与无障碍等能力;Iced 的渲染器当时尚未包含这些特性,因而 native 质感较弱;
- WGPU 成熟度:文档如实承认 Dioxus 的 WGPU 渲染器当时尚不成熟、不适合产品开发,而 Iced 的 WGPU 渲染器已经可用于生产——因此强 GPU 场景下 Iced 可能是更现实的选择(这一点恰好也呼应“Dioxus WGPU 仍属实验性”的平台表描述)。
与 Electron:轻量哲学与成熟度差距
- 轻量:Dioxus 复用系统自带 webview(或可选 WGPU)渲染 UI;对比之下典型 macOS 应用中 Electron 占用约 100mb 而 Dioxus 应用约 15mb(文档当时口径;当前 README 已更新为 <5mb)。Electron 内嵌的 Chromium 不像 Dioxus 那样共享系统资源;
- 成熟度:Electron 拥有庞大社区与工具链;文档坦言 Dioxus 与之相比仍年轻,像 deep link 这类需要额外投入的特性仍在建设中。
文档、开发者体验与社区
翻译文档中“Fantastik Dökümantasyon”(出色的文档)一节指出:所有 HTML 元素与监听器都对照 MDN 编写文档,且官方文档站用 Dioxus 自身构建、与 Dioxus 的 CI 保持集成,确保文档不过时。仓库同样贯彻了这一理念:不仅有面向贡献者的 CONTRIBUTING.md、RELEASING.md 与 FAQ.md,还有一套面向深度开发者的架构文档目录(覆盖核心、CLI、RSX、信号、全栈、渲染器、热重载、资源、路由、WASM 拆分等主题),并有中文、日文、韩文、葡萄牙文等多语言 README 译本(如 中文译本)。
在开发者体验上,官方提供了 VSCode 扩展(仓库内实现见 packages/extension),支持 RSX 自动格式化、把 HTML 转换为 RSX 等功能;配合强大的 CLI,开发者可以完成新项目生成、serve与跨平台打包,文档称部署能力也已进入路线图。社区方面,Dioxus 有活跃的 Discord 与 GitHub issue 体系,官方 SDK 与若干精选 crate 托管在社区 GitHub 组织下。
开源治理与许可
翻译文档记录了一个重要背景:Dioxus 从副业项目成长为一支全职小团队,先后获得 FutureWei、Satellite.im 与 GitHub Accelerator 项目的支持;团队长期目标是通过提供高质量付费企业工具让项目实现自我造血。
许可方面,翻译文档文末写的是“本项目基于 MIT 许可”,并说明未另行声明时,贡献默认按 MIT 授权。需要留意的是,仓库当前主 README.md 与根目录下同时存在的 LICENSE-APACHE / LICENSE-MIT 两份文件表明:当前正式许可是 MIT 或 Apache-2.0 双许可,贡献默认按任一许可授权而无需额外条款。若你打算参与贡献,应以当前主仓库的许可声明为准。
小结:文档骨架之外,如何在仓库中继续深入
本文的脉络完全跟随翻译文档展开——从最小计数器示例、独有特性、热重载与打包,到平台矩阵、示例运行、六大框架对比与社区许可。若想进一步验证或深挖,本仓库提供了逐层的进阶路径:阅读英文主 README.md 获取最新特性描述;翻阅 架构文档 00-OVERVIEW 弄清 crate 依赖与渲染器架构;在 04-SIGNALS.md 中研究信号与响应式内核的实现细节;最后用 packages/cli/README.md 上手 CLI 与Dioxus.toml配置,再把 examples 目录下任意一个示例跑起来,即可完整体验“一套 Rust 代码库,多端全栈交付”的开发流程。
【免费下载链接】dioxusFullstack app framework for web, desktop, and mobile.项目地址: https://gitcode.com/GitHub_Trending/di/dioxus
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考