一年的狄克修斯全程生产:好,痛苦
在本页( 5 节)
经过一年的狄克修斯·费斯达克的制作,"鲁斯特"代码是我业务中最无聊的部分。 CI是最激动人心的部分,不尽人意:发布会的建设需要90分钟GitHub主持人跑跑。
当年从我之前的工作开始,继续使用我自己的产品。 回到4月,我写了为什么我选了Rust来制作一个微型SaaS。 短版本:起步较慢,较后期生活更便宜。 此帖为帐。
我所追求的
SeggWat是SaaS产品的一个应用中反馈工具。 它的仪表板是一款Dioxus 0.7 fulstack app into a Cargo 工作空间:一个具有服务器功能的后端箱子,一个认证箱,以及大约10个UI 箱子,涵盖洞察力,反馈,想法,板子,部件和设置。 十二个箱子要靠二氧化物所有东西都放在PostgreSQL上
下面的页面建在同一堆上。
“Fullstack”是指从事三项工作的Rust Codebase。 它在服务器上制作,将服务器功能作为后端运行,并将客户端编译到WebAssembly,使页面变得交互。
不错
一言为定
数据库查询,业务规则,服务器功能,按钮:全部Rust. 一个工具链一个物料一套习惯当某事破裂时一个地方看
在你成为独行创始人之前,我没有“前端大脑”和“后端大脑”,我打开工作空间继续前进
两边都一样
我最想念的就是这个。
一个结构得到定义一次。 数据库层返回,服务器函数发送,组件生成。 当我重命名一个字段,货物检查给我列表每一个地方,包括UI。 没有 OpenAPI 光谱可以再生,也没有 TypeScript 接口会与后端同步漂移。
胜利并没有更快地写出代码。 却没人去检讨。
其他平台的大门仍然敞开
Dioxus可以从同一种组件模型中瞄准桌面和移动,包括iOS. 今天我的产品都不需要本地的应用软件但当我决定把一年的工作放在哪里时,我知道我可以不重写地运送一个。
生产很无聊
这就是重点所在。 一旦编译出来,它大多只是运行。 一整类的"未定义不是函数"bug从未触及到用户,因此确实通过bug是逻辑bug. 我宁愿把注意力花在那里。
4月份的“生产中的困难”论点与真正的用户保持了联系。
难受
编译时间
这是路斯特福音者倾向于跳过的部分。
仪表盘会编译出两次:一次是给服务器的,而一次是给浏览器的取自正版32. 一打狄克修斯的箱子加上一个大重的UI加起来在本地,我的工作流程文件中的评论就像日记一样:
- 单是WASM就花了大约22分钟 6个核心。 这是单一的叶子箱:为浏览器编译的仪表板。
- 一个发布图像需要大约90分钟在GitHub主持双核跑者。 以我个人的VPS选手来说
- Clippy被OOM杀死了 7GB主机跑道上的货物剪接 -- -- 工作空间 -- -- 所有目标死亡退出码143 完全没有诊断。 固定为10GB互换文件外加CARGO BUILD JOBS=1来剪去峰值内存。 我的灯关需要交换。
在某个时候,我停止了在每次推向主线上建立图像。 他们现在依靠释放标记或者当我用手触发它们时因为每次推动90分是花钱的愚蠢方式
我试过的
- 用斯瓦蒂内姆/破伤风卡切但有一个陷阱。 一个工作流程运行只能从自己的ref或默认分支中恢复缓存,而GitHub则会驱逐未使用7天的缓存。 一旦我停止在主上建设,释放开始冷。 我的工作几乎很有趣:在依赖性崩溃之后,我手动触发一个主线的建构,只是为了保持缓存的温暖。
- 建造和测试一个去,所以测试再利用汇编了文物而不是第二次汇编世界。
- 模具连接器不错,但联系从来不是瓶颈。 编曲是。
- 重型建筑的自营跑者这是迄今为止最大的赢家,90分钟减为40分。 这也意味着我现在维持一个构建服务器。
这些都帮了忙它们都没有改变基本的数学:两个编译目标,一个大依赖树和很多宏意味着很多编译。
"一地一地"有星号
商业逻辑是所有 Rust. 情况并非如此。
SeggWat的见解页面显示图表,因此图是Chart.js,由CDN装入并被约340行的JavaScript包裹,狄克修斯通过二oxus-use-js调用。 Styling是Tailwind,因此CI也安装了Bun并运行了"Tailwind CLI"在Rust甚至开始之前。
我不介意,这是务实的。 如果你选择Dioxus来逃离JavaScript
我会再做一次吗?
人们问道,“什么帮助我最快的船?” 更好的问题是:“什么能帮助我保持航运而不恨我的生活?”
对于后端,答案仍然是Rust
我改变主意了。 如果我在建立真正像应用程序的东西,有沉重的客户端状态,离线支持或真正的移动应用程序,但我所建造的大多是仪表板:表格、表格、几张图表和一些切换。 我对每次放行都要缴纳22分钟的瓦斯M税
接下来是什么:Topcoat
因此,我的下一个项目是使用Topcoat,一个新的满层框架从tokio -rs org,宣布在7月。
它让相反的赌注从狄克修斯。 服务器上的一切,组件都是可以直接查询数据库的Async函数。 对于交互性,您用普通的,按类型检查的 Rust 写出 $(.) 表达式。 Topcoat在服务器上评价它们进行第一个渲染,并把它们翻译为JavaScript,因此它们立刻在浏览器中重新运行。 没有WASM捆绑,也没有第二个编译目标。
自动同步
从Topcoat README的示例。
在纸上,Topcoat保留了我喜欢的关于Dioxus(一种语言,共享类型,没有API层),并去除最伤害的部分,即22分钟的WASM构建。
说清楚,这是赌注,不是结果。 Topcoat的README称其为早期和实验性,预计会有突破性变化。 我放弃多平台选项。 我还没有衡量任何一座建筑。
我会用真实的数字来写后续:编译时间,CI分钟,若我的释放时间从40分钟降至10分钟,如果不是这样,你也会听到这一点。
我是Hauke。 我用Rust建造了SeggWat、Stepshot和下页,并在OXIDT上写作。
本文由 AI宝库自动抓取并翻译,版权归原作者所有;如需查看原文请点下方链接。
One year of Dioxus fullstack in production: the good, the painful
On this page (5 sections)
After a year of Dioxus fullstack in production, the Rust code is the most boring part of my business. CI is the most exciting part, and not in a good way: a release build takes 90 minutes on a GitHub-hosted runner.
That year started at my previous job and continued on my own products. Back in April I wrote about why I picked Rust for a production micro SaaS. The short version: slower at the start, cheaper to live with later. This post is the bill.
What I’m running
SeggWat is an in-app feedback tool for SaaS products. Its dashboard is a Dioxus 0.7 fullstack app inside a Cargo workspace: a backend crate with server functions, an auth crate, and about ten UI crates covering insights, feedback, ideas, boards, widgets and settings. Twelve crates depend on dioxus. Everything sits on PostgreSQL.
infra.page is built on the same stack.
“Fullstack” means one Rust codebase doing three jobs. It renders on the server, runs server functions as the backend, and compiles the client to WebAssembly so the page becomes interactive.
The good
One language, all the way down
Database query, business rule, server function, button: all Rust. One toolchain, one formatter, one set of habits, one place to look when something breaks.
That sounds minor until you’re a solo founder juggling several products. I don’t have a “frontend brain” and a “backend brain” that each need warming up. I open the workspace and keep going.
The same types on both sides
This is the one I’d miss most.
A struct gets defined once. The database layer returns it, the server function sends it, and the component renders it. When I rename a field, cargo check gives me a list of every place that broke, including the UI. There’s no OpenAPI spec to regenerate and no TypeScript interface drifting out of sync with the backend.
The win isn’t writing code faster. It’s refactoring without fear, late at night, with nobody to review it.
The door to other platforms stays open
Dioxus can target desktop and mobile, including iOS, from the same component model. None of my products needs a native app today. But knowing I could ship one without a rewrite mattered when I decided where to put a year of work.
Production is boring
That’s the whole point. Once it compiles, it mostly just runs. A whole class of “undefined is not a function” bugs never reaches users, so the bugs that do get through are logic bugs. That’s where I’d rather spend my attention anyway.
The “boring in production” argument from April survived contact with real users.
The painful
Compile times
This is the part Rust evangelists tend to skip.
The dashboard compiles twice: once for the server and once to wasm32 for the browser. A dozen Dioxus crates plus a macro-heavy UI add up. Locally it’s tolerable on a decent machine. CI is a different story, and the comments in my workflow files read like a diary of it:
- The WASM build alone takes about 22 minutes on 6 cores. That’s a single leaf crate: the dashboard compiled for the browser.
- A release image takes about 90 minutes on a GitHub-hosted 2-core runner. On my own VPS runner it’s around 40, and that’s the good version.
- Clippy got OOM-killed. cargo clippy --workspace --all-targets on the 7 GB hosted runner died with exit code 143 and no diagnostics at all. The fix was a 10 GB swapfile plus CARGO_BUILD_JOBS=1 to cut peak memory. My linter needs swap.
At some point I stopped building images on every push to main. They now build on release tags or when I trigger them by hand, because 90 billed minutes per push is a silly way to spend money.
What I tried
- Caching with Swatinem/rust-cache. It helps, but there’s a trap. A workflow run can only restore caches from its own ref or the default branch, and GitHub evicts caches unused for 7 days. Once I stopped building on main, release builds kept starting cold. My workaround is almost funny: after a dependency bump, I manually trigger a build on main just to keep the cache warm.
- Building and testing in one go, so the tests reuse compiled artifacts instead of compiling the world a second time.
- The mold linker. Nice, but linking was never the bottleneck. Compiling was.
- A self-hosted runner for the heavy builds. This was by far the biggest win, 90 minutes down to 40. It also means I now maintain a build server.
Every one of these helped. None of them changed the underlying math: two compile targets, a big dependency tree and lots of macros means a lot of compiling.
“All Rust” comes with an asterisk
The business logic is all Rust. The edges aren’t.
SeggWat’s insights page shows charts, and I couldn’t find a Rust charting library I’d trust in production. So the charts are Chart.js, loaded from a CDN and wrapped in about 340 lines of JavaScript that Dioxus calls through dioxus-use-js. Styling is Tailwind, so CI also installs Bun and runs the Tailwind CLI before Rust even starts.
I’m fine with that. It’s pragmatic. But if you’re choosing Dioxus specifically to escape JavaScript, know what you’re signing up for: Rust, plus some JS glue, plus a JS toolchain in your pipeline.
Would I do it again?
People ask, “What helps me ship fastest?” The better question is, “What helps me keep shipping without hating my life?”
For the backend, the answer is still Rust, and it isn’t close.
For the frontend, I’ve changed my mind a bit. If I were building something truly app-like, with heavy client state, offline support or a real mobile app, I’d pick Dioxus again. But most of what I build is dashboards: forms, tables, a few charts and some toggles. For that, I’m paying a 22-minute WASM tax on every release for interactivity I barely use.
What’s next: Topcoat
So my next project is going to use Topcoat, a new fullstack framework from the tokio-rs org, announced in July.
It makes the opposite bet from Dioxus. Everything renders on the server, and components are async functions that can query the database directly. For interactivity, you write $(...) expressions in ordinary, type-checked Rust. Topcoat evaluates them on the server for the first render and also translates them to JavaScript, so they re-run instantly in the browser. There’s no WASM bundle and no second compile target.
async
Example from the Topcoat README.
On paper, Topcoat keeps what I love about Dioxus (one language, shared types, no API layer) and removes the part that hurts most, the 22-minute WASM build.
To be clear, this is a bet, not a result. Topcoat’s README calls it early-stage and experimental, with breaking changes expected. I’m giving up the multi-platform option. And I haven’t measured a single build yet.
I’ll write the follow-up with real numbers: compile times, CI minutes, and whatever I end up missing from Dioxus. If my release build drops from 40 minutes to 10, you’ll hear about it. If it doesn’t, you’ll hear about that too.
I’m Hauke. I build SeggWat, Stepshots and infra.page in Rust and write about it on OXIDT.
Auto-fetched and translated by AI Gem Box. All rights belong to the original author.