logoalt Hacker News

Farewell, Rust for web

84 pointsby skwee357today at 6:42 PM67 commentsview on HN

Comments

robvirentoday at 8:16 PM

I find the dependency creep for both rust and node unfortunate. Almost anything I add explodes the deps and makes me sweat for maintenance, vulnerabilities, etc. I also feel perpetually behind, which I think is basically frontend default mode. Go does the one thing I wish Rust had more of which is a pretty darn great standard library with total backwards compatibility promises. There are awkward things with Go, but man, not needing to feel paranoid and how much can be built with so little feels good. But I totally understand just getting crap done and taking off the tin foil. Depends on what you prioritize. Solo devs don't have the luxury.

show 7 replies
tracker1today at 9:58 PM

I would assume today that maybe Dioxus or Leptos would be considered. Though that would be the "all in" approach on Rust front to back... it wouldn't really reduce some of the handling conditions levied in the article though.

I find C# can be a really good middle ground on the backend (not a blazor fan)... the syntax and expressiveness improves with every release. You can burrow as lot of patterns from the likes of Go as well as FP approaches. What I don't care for are excessively complex (ie: "Enterprise") environments where complexity is treated like a badge of honor instead of the burden of spaghetti that it is in practice.

wofotoday at 8:53 PM

I'm a heavy Rust user and fan, but I'd never pick Rust for web. There are way more mature ecosystems out there to choose from. Why would you waste "innovation tokens" in a Rust-based web application?

show 1 reply
andrewayletttoday at 9:09 PM

It's a throwaway comment in the article, but I feel it's important to push back on: HTML is very definitely a programming language, by any reasonable definition of "programming language".

Edit to add: It might not be an imperative language, but having written some HTML and asked the computer to interpret it, the computer now has a programmed capability, determined by what was written, that's repeatable and that was not available apart from the HTML given. QED.

show 2 replies
NewJazztoday at 8:46 PM

due to the nature of safety in Rust, I’d find myself writing boilerplate code just to avoid calling .unwrap(). I’d get long chain calls of .ok_or followed by .map_err. I defined a dozen of custom error enums, some taking other enums, because you want to be able to handle errors properly, and your functions can’t just return any error.

This can be a double edged sword. Yes, languages like python and typescript/JavaScript will let you not catch an exception, which can be convenient. But that also often leads to unexpected errors popping up in production.

mrbluecoattoday at 7:48 PM

Better title: "Farewell, Rust for Web"

show 4 replies
chrashtoday at 8:53 PM

the idea of one language to rule them all is very compelling. it’s been promised a lot, and now everyone hates Java.

but the truth is that Rust is not meant for everything. UI is an abstraction layer that is very human and dynamic. and i can come and say, “well, we can hide that dynamism with clever graph composition tricks” à la Elm, React, Compose, etc, but the machinery that you have to build for even the simplest button widget in almost every Rust UI toolkit is a mess of punctuation, with things like lifetimes and weird state management systems. you end up building a runtime when what you want is just the UI. that’s what higher level languages were made for. of course data science could be done in Rust as well, but is the lifetime of the file handle you’re trying to open really what you’re worried about when doing data analysis?

i think Rust has a future in the UI/graphics engine space, but you have to be pretty stubborn to use it for your front end.

show 1 reply
Paul-Etoday at 8:00 PM

I want to address this one point:

> Similar thing can be said about writing SQL. I was really happy with using sqlx, which is a crate for compile-time checked SQL queries. By relying on macros in Rust, sqlx would execute the query against a real database instance in order to make sure that your query is valid, and the mappings are correct. However, writing dynamic queries with sqlx is a PITA, as you can’t build a dynamic string and make sure it’s checked during compilation, so you have to resort to using non-checked SQL queries. And honestly, with kysely in Node.js, I can get a similar result, without the need to have a connection to the DB, while having ergonomic query builder to build dynamic queries, without the overhead of compilation time.

I've used sqlx, and its alright, but I've found things much easier after switching to sea-orm. Sea-orm has a wonderful query builder that makes it feel like you are writing SQL. Whereas with sqlx you end up writing Rust that generates SQL strings, ie re-inventing query builders.

You also get type checking; define your table schema as a struct, and sea-orm knows what types your columns are. No active connection required. This approach lets you use Rust types for fields, eg Email from the email crate or Url from the url crate, which lets you constrain fields even further than what is easy to do at the DB layer.

ORMs tend to get a bad reputation for how some ORMs implement the active record pattern. For example, you might forget something is an active record and write something like "len(posts)" in sqlalchemy and suddenly you are counting records by pulling them from the DB in one by one. I haven't had this issue with sea-orm, because it is very clear about what is an active record and what is not, and it is very clear when you are making a request out to the DB. For me, it turns out 90% of the value of an ORM is the query builder.

show 1 reply
fuddletoday at 8:02 PM

The TS/React ecosystem is so mature, it's hard for Rust to compete with it. My optimal stack is currently: Rust on the backend, Typescript/React for web with OpenAPI for shared types.

show 3 replies
eYrKEC2today at 8:48 PM

I looove Rust for the backend.

I've supported backends in typescript, python, Java, and Rust.

Rust pages me the least at night. Sleep is beautiful.

taylorallredtoday at 8:59 PM

Rust shines in user-space systems-level applications (databases, cloud infrastructure, etc.) but definitely feels a bit out of place in more business-logic heavy applications.

bryanlarsentoday at 7:54 PM

Rust for Web is awesome for adding control interfaces etc to other programs who have a different primary purpose.

And even then I do it by serving JSON API's and not by serving HTML.

stevagetoday at 9:22 PM

> And the occasional struggles with typescript where the runtime seems to be changing too often; is it ts-node? tsx? tsm? The built-in typescript runtime in node? deno? bun?

This whole paragraph is so true. The last couple of years have been pretty rough in Node land.

zemtoday at 9:18 PM

rescript [https://rescript-lang.org/] would make a nice middle ground between rust and typescript

cyberaxtoday at 7:55 PM

Well, yep. People underappreciate the Typescript/JS ecosystem.

Typescript is pretty type-safe, and it's perfectly integrated with hot code reload, debuggers, and all the usual tools. Adding transpilation in that flow only creates friction.

That's also why things like Blazor are going nowhere. C# is nicer than Typescript, but the additional friction of WASM roundtrips just eats all the advantage.

show 1 reply
slopinthebagtoday at 9:42 PM

As someone who went in the opposite direction from Node to Rust, I feel like OP is just trading one set of problems for another set of substantially worse problems. I guess the grass is always greener in the other ecosystem ¯\_(ツ)_/¯

Idk, it just feels like OP chose all the wrong approaches with Rust, including using a separate language and ecosystem for the frontend, which is where most of the friction comes from. For example, Dioxus is a React clone that is somehow leagues better than React (and Next.js, too), and it has hot-reloading that brings compiles down to subsecond times, which makes building UI with it just as productive as with Node / Vite etc. I use it for server side code as well and it's great. Compilation times can be an issue with Rust, it's something I miss from Go, but there are ways to improve on it, and just being smart about what deps you include, avoiding overuse of macros etc can make a difference. I know these things were not around when OP started using Rust for their application, but they are around now.

Node and TS are quite frankly inferior to Rust in most ways. Bad language, ecosystem full of buggy unmaintained packages with the worse security profile of all the common languages, no unified build tooling that seems to break your project every 6 months, constant churn of blessed frameworks and tools, an stdlib that is not much more comprehensive than Rust's and outright broken in some ways, at least three different approaches to modules (esm, commonjs, umd, and more...?), I could go on an on. There is a reason why everyone seemingly reinvents the wheel in that ecosystem over and over again -- the language and platform is fundamentally not capable of achieving peoples goals, and every solution developed comes with massive tradeoffs that the next iteration attempts to solve, but that just creates additional issues or regressions for future attempts to tackle.

I've been using Rust with Dioxus and was completely mind blown when I started with it. With barely knowing any Rust (just React) I was able to jump right in and build with it, somehow it was more intuitive to me than most modern JS full stack frameworks. It seemingly already has most if not all of the features that similar JS frameworks have been developing for years, and because it's written in Rust things like conditional compilation are built into the language instead of being a third party babel plugin. That helps to remove a ton of friction. And it's trivial to build those same apps for desktop and mobile as well, something that's basically not possible with the JS frameworks.

Even stuff like websockets, go try to implement a type safe web socket connection with a server and client in Next.js or Astro. You'll need a ws library, something like Zod for validation, etc. In Rust it's just:

   #[derive(Serialize, Deserialize, Clone, Default)]
   enum SocketMessage { Hello(id: i32) }
  
   #[get("/api/ws")]
   async fn web_socket(options: WebSocketOptions) -> Websocket<SocketMessage> {
     options.on_upgrade(move |mut socket| async move {
       while let Ok(msg) = socket.recv().await {
         match msg { SocketMessage::Hello(id) => {} } // handle messages
       }
     })
   }

   fn App() -> Component {
     let mut socket = use_websocket(web_socket);
     rsx!{ button { onclick: move || socket.send(SocketMessage::Hello(42), "say hello" } }
   }
show 1 reply
clarabennett26today at 8:43 PM

[dead]

ewuhictoday at 7:39 PM

[flagged]

show 1 reply
PowerElectronixtoday at 7:45 PM

[flagged]

show 1 reply
aaroninsftoday at 7:54 PM

This is oddly timed in as much as one of the big success stories I've heard from a friend is their new practice of having Claude Code develop in Rust, than translate that to WebAssembly.

That seems much more like the future than embracing Node... <emoji here>

show 1 reply