6 ms·
Porting a JavaScript App to WebAssembly with Rust (Part 1)
- austincheney 7y ago> Maintaining Software that is written in a dynamically typed language like JavaScript is costly. Maintaining a JavaScript frontend that is build with React, NPM, WebPack and Babel is even more expensive. Not exactly. In modern browsers JavaScript executes in a VM. If the JavaScript instance is written in a strongly typed way it executes quickly by receiving the full benefits of a compiled language. Aside from arithmetic it executes almost as fast as Java. That is one of the strengths of TypeScript. I do completely agree about NPM, dependency overkill, and framework insanity. In short, don’t blame the language for being slow. Blame marketing and bad developers. That being said I have little faith that WASM will be fast once it meets the reality of bad developers and marketing teams.
- jlelse 7y agoI think that quote isn't about JS performance but maintaining software written in JS.
- austincheney 7y agoAgain, that goes to the quality of product/people in a given instance. I have done this long enough to fully appreciate that when it comes to fucking up software on the web people will find a way whether it’s for some poorly conceived developer motivation or media/marketing motivation.
- bsaul 7y agoi think the original post just mentionned « costly ». It didn’t say it was impossible to mess things up even with rust. Just that it removes the cost of checking types are still matching after a refactoring or a dependency update.
- The_rationalist 7y agoTypescript allow that too.
- rienbdj 7y agoThis a true, but the advantage is probably more than offset by the relative cost of JS vs Rust developers. You can also add Flow types. A single threaded environment does not yield the usual advantages of the Rust borrow checker.
- zozbot234 7y ago> the relative cost of JS vs Rust developers I.e. pay peanuts, get code monkeys? > A single threaded environment does not yield the usual advantages of the Rust borrow checker. This is quite wrong - reference invalidation and async code that's being scheduled within a single thread are two common examples where it matters a lot.
- Eikon 7y agoLots of boilerplate and error-prone code can also be avoided by implementing `drop` on relevant types, this can yield to pretty interesting APIs in the web space.
- steveklabnik 7y agoThe borrow checker still helps quite a bit with a single thread: http://manishearth.github.io/blog/2015/05/17/the-problem-with-shared-mutability/ http://manishearth.github.io/blog/2015/05/17/the-problem-wit...
- ossworkerrights 7y agoBut rust is trendy so anything that is not rust is crap. I find it amusing when people blame technology for their own shortcomings, and think using a different language will improve things only to end up using the new lang just as bad. You are getting downvoted because there is just too much religion surrounding tech x vs tech y on hackernews and some people imagine rust is great for the web as if the world will suddenly drop tried and tested languages, with loads of tools and documentation available, with package manager and nearly ubiquitos support in favour of a fringe language like rust.
- rienbdj 7y agoThis argument is a bit... tired. There are genuine advantages to different technologies and we should explore them. Every article about rewrites (not only Rust) is met with this sort of comment and it is counter productive. If someone is claiming a technology is better in some way and you disagree, explain why they are mistaken.
- austincheney 7y ago> There are genuine advantages to different technologies That is also a tired argument. The compile target is WASM. Rust can be the greatest thing ever, but the performance that matters and the only limitations the user will see are those inherent to WASM. Is WASM multithreaded with the execution speed of a Rust binary? No, so who cares?
- rienbdj 7y agoThe process of generating the WASM is entirely different. C, C++ and Rust all generate x86 assembly but they have very different trade offs. Following this line of reasoning writing raw WASM would also be a fine choice!
- austincheney 7y agoIt certainly isn't HN. It's everywhere. Reddit was worse by an order of magnitude and poorly moderated. I don't even think WASM executes faster than JavaScript in any meaningful metric. The strongest motivation, from developers that are not in any way involved in the WASM spec, is a shimmering hope that developers will be off the hook for writing JavaScript. In the context of "replacing JavaScript" type threads this results in the religious fascination that you and others have observed, but in other contexts comments are equally up-voted for their critical examination: https://news.ycombinator.com/item?id=21723071 https://news.ycombinator.com/item?id=21723071
- tiborsaas 7y agoI think he might have referred to costly in business sense, because more bugs lead to more developer hours spent.
- fnord77 7y ago> In the next series we'll see how to translate the legacy JavaScript code to working Rust code. this is the part I came to see.
- sammorrowdrums 7y agoDid anyone find a subscribe link? I'm curious to see how this progresses.
- arusahni 7y agohttps://slowtec.de/feed.rss https://slowtec.de/feed.rss
- bobajeff 7y agoThis is cool. I'll be paying attention to this. If for no other reason than to see what it's like porting from one language to another.
- Rotten194 7y agoI thought DOM manipulation from WASM was pretty expensive because it needs to be bridged through JS -- is that still true?
- Eikon 7y agoUnfortunately it is, you may want to have a look at: https://krausest.github.io/js-framework-benchmark/current.html https://krausest.github.io/js-framework-benchmark/current.ht... Filter for wasm frameworks like “Yew”.
- McWobbleston 7y agoThere's wasm benchmarks that don't trail much behind vanilla JS, though.
- steveklabnik 7y agoThere’s a lot of variance here. See https://ivanceras.github.io/sauron-perf/ https://ivanceras.github.io/sauron-perf/ too. New versions of libraries, new optimizations in browsers... the numbers are changing all the time.
- stefano 7y agoYou still need to go call into Javascript to do any kind of DOM manipulation. The solution I used for wasm-forth (a forth implementation targeting wasm), is to have a js "interpreter", implemented as a single function, that executes a sequence of DOM manipulation instructions, represented as an array of integers. On the forth side, the instructions are generated by a virtual DOM library: as the virtual DOMs are diffed, instead of manipulating the DOM directly it generates a sequence of opcodes to send in one go to the Javascript interpreter. The cost of the Javascript bridge is minimal: it's a single function call to render or update a whole page, and there is no serialization/deserialization involved since both languages can understand arrays of integers natively.
- lytedev 7y agoThis is a really neat idea! Was there an inspiration for this? I think something like this could be very useful!
- pythux 7y agoInteresting take, but there is no indication that the new Rust-based stack will be « less expensive » to maintain than the current one. I am curious to see the next posts in the series. I would also like to know if they considered other alternatives; they mention Elm, what about TypeScript. The issues they mention seem to also have to do with the specific choice of frameworks or tools: React, Webpack, etc. Not so much with JavaScript itself?
- cerved 7y agoWhile it's just part one, I feel like whether the end result successfully overcomes the problems mentioned is missing. I wonder if in fact it does. Personally I wouldn't refactor an entire application from scratch unless it was fairly simple. Instead I prefer incremental refactoring and I've found that typescript can be helpful in that regard.
- amenod 7y agoAlso, while Rust does bring additional guarantees to the table, I wonder if they are really the ones that matter (much) in web dev. Having a strongly typed language is a bonus, but a) there is TypeScript and b) the maintainability nightmares I have encountered had nothing to do with the language itself, but more with core programming principles like separation of concerns, state management (well, I'll admit that existance of MobX doesn't help there...) and similar. So I don't buy the motivation, but it's still interesting to see what can be done in Rust.
- gedy 7y ago> well, I'll admit that existance of MobX doesn't help there... 'Doesn't' or 'does'? We've found MobX to really help.
- 52-6F-62 7y agoSo have I. MobX + TypeScript has been one of the better experiences I’ve had.
- amenod 7y agoDoesn't, imho of course. MobX makes creating and using global variables way too easy. One of the more nightmarish legacy projects included hunting down the culprit that sometimes changed some variable in mobx store. Abysmall tooling (compared to Redux) doesn't help either. Currently my go-to store is Redux Toolkit [0]. Explicit store management, but much less verbose than regular Redux. Also, initial state, actions and reducers are all defined in one place (slice). [0] https://redux-toolkit.js.org/ https://redux-toolkit.js.org/
- jorblumesea 7y agoThis seems like a solution looking for a problem but cool to see. A far more practical suggestion would be to just use typescript and incrementally rewrite.
- Tade0 7y agoWhile I love Rust, I don't think this here is a good use case for it - TypeScript nowadays works really well with JSX and can be introduced incrementally. Rust's guarantees work best in a highly concurrent setting - a web app isn't really one. Rust shines not on the application level, but on the framework/library level, where things like memory usage and performance are critical. A framework with virtual DOM written entirely in Rust would go a long way. Same with a template compiler.
- gedy 7y agoWhile really cool, this is my big concern about web assembly (in a 'real company' doing boring stuff) - devs using in browser for UI/app stuff and fragmenting simple use cases across their favorite languages. Love your idea of frameworks leveraging for core parts like vdom though.
- maxyme 7y agoI've ported a template compiler to Rust before. The reality is you still end up with something slower than native JS because of the overhead serializing and parsing the JSON in WASM memory. This is something that will be helped by the interface types proposal[0] if it is implemented but I was surprised that this use case didn't work as well as I thought it would. [0] https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md https://github.com/WebAssembly/interface-types/blob/master/p...
- shpongled 7y agoI use Rust all the time, where 90% of what I write is on the application level, and 5% is concurrent. I just like the language.
- eggsmediumrare 7y agoEnjoying the language you're using is as important as pretty much anything else.
- batmansmk 7y agoBoth virtual dom and template compilers exist in Rust: Yew for instance uses both to provide a React-like experience: https://github.com/yewstack/yew https://github.com/yewstack/yew JSX is easy to implement in Rust due to the fact that macros are first class citizen in Rust.
- pkolaczk 7y agoWhile Rust is a very cool technology, I don't think it is the best tool for web development. Manual memory management and constant thinking about ownership and memory sharing is additional productivity overhead, and you don't gain anything from it because the final code is running in a GCed runtime anyways. I'd use TypeScript or Scala.js.
- djur 7y agoWebAssembly code has to do its own memory management anyway. You don't get the benefits of the JavaScript GC.
- pkolaczk 7y agoI didn't say you got benefits of JS GC nor lack of JS GC. And that's the point: you don't get benefits, but you pay the price in lower productivity. Rust is a pleasant language to write in, but it is nowhere as expressive and fast to develop in as TypeScript, Scala or even Kotlin.
- vmind 7y agoI've found Rust is great for doing heavy lifting (parsing/compiling/graph analysis, etc) on the frontend, as long as you can define the boundary between wasm/JS reasonably cleanly. And in that code I don't think there's a productivity hit as you can benefit a lot from the stricter types (ADT pattern matching, etc) and more reliable performance. For more straightforward UI code, I'd agree that TypeScript strikes a much better balance right now, especially for (almost) seamlessly working with the wider ecosystem. I moved away from Scala.js because defining the boundary transition was quite error prone, but maybe I was missing something.
- crtlaltdel 7y agohttps://www.youtube.com/watch?v=kY-pUxKQMUE https://www.youtube.com/watch?v=kY-pUxKQMUE seriously though, i’ve been very interested to see how webassembly adoption goes. does anyone have examples of new projects implemented in webassembly? i’ve seen lots of examples of ports, but am more curious about its use in product development.
- mattlondon 7y agoSounds like typescript and angular would be a better fit here. Angular is "batteries included" compared to react, so you generally won't hit the same dependency hell since angular comes with pretty much everything you need (although not redux pattern support (yet)). Typescript is a strictly-typed JavaScript. Reprogramming a web front end in rust sounds like a way to lead to huge maintenance issues in the future (i.e. you need to find developers who know rust AND how frontends and things like redux actually work - you'll probably get someone who is good at one, and half-assed at the other). I am also uncertain how you'd debug things in the browser for wasm - e.g. would the redux Dev tools work? Where I see wasm as useful is if you are doing any heavy-lifting in the browser - so all the examples they give on the various web sites about games and cryptography etc, but probably also parsing/serialisation of binary data from the server for example. I don't feel like basic SPA stuff is a good fit.