2018-08-26 22:16:42 -04:00
|
|
|
---
|
|
|
|
layout: post
|
|
|
|
title: "Isomorphic Desktop Apps with Rust"
|
2018-09-09 01:02:58 -04:00
|
|
|
description: "Electron + WASM = ☣"
|
2018-08-26 22:16:42 -04:00
|
|
|
category:
|
2018-09-09 01:02:58 -04:00
|
|
|
tags: [rust, javascript, webassembly]
|
2018-08-26 22:16:42 -04:00
|
|
|
---
|
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
Forgive me, but this is going to be a bit of a schizophrenic post. I both despise Javascript and the
|
|
|
|
modern ECMAScript ecosystem, and I'm stunned by its success at doing some things I think are really cool.
|
|
|
|
And it's [this duality](https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript)
|
|
|
|
that led me to a couple of (very) late nights over the past weeks trying to reconcile myself.
|
2018-08-26 22:16:42 -04:00
|
|
|
|
2018-08-27 00:20:49 -04:00
|
|
|
See, as much as [Webassembly isn't trying to replace Javascript](https://webassembly.org/docs/faq/#is-webassembly-trying-to-replace-javascript),
|
2018-09-09 01:02:58 -04:00
|
|
|
**I want Javascript gone**. There are plenty of people who do not share my views, and they are probably
|
|
|
|
nicer and more fun at parties. But I cringe every time "Webpack" is mentioned, and I think it's hilarious
|
|
|
|
that the [language specification](https://ecma-international.org/publications/standards/Ecma-402.htm)
|
|
|
|
dramatically outpaces anyone's [actually implementing](https://kangax.github.io/compat-table/es2016plus/)
|
|
|
|
the spec. The answer to this conundrum is of course to have a "polyfill" that translates
|
2018-08-27 00:20:49 -04:00
|
|
|
code from newer versions of the language to older versions of the language. At least
|
2018-09-09 01:02:58 -04:00
|
|
|
[Babel] is a nice tongue-in-cheek reference.
|
2018-08-26 22:16:42 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
And yet, for as much hate as [Electron] receives, it does a stunningly good job at solving
|
2018-08-27 00:20:49 -04:00
|
|
|
a really hard problem: *how the hell do I put a button on the screen and react when the user clicks it*?
|
|
|
|
GUI programming is hard, straight up. But if browsers are already able to run everywhere, why don't
|
2018-09-09 01:02:58 -04:00
|
|
|
we take advantage of someone else solving the hard problems for us? Don't reinvent wheels. I don't like
|
|
|
|
that I have to use Javascript for it, but I apparently don't mind Javascript enough that I feel inclined to
|
|
|
|
whip out good ol' [wxWidgets].
|
2018-08-26 22:16:42 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
Now, there are other "native" solutions ([libui-rs], [conrod], [oh hey wxWdidgets again!][wxRust]),
|
2018-08-27 00:20:49 -04:00
|
|
|
but those also potentially have their own issues with distribution, styling, etc.
|
|
|
|
With Electron, I can `yarn create electron-app my-app` and just get going, knowing that distribution/upgrades/etc.
|
|
|
|
are built in.
|
2018-08-26 22:16:42 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
So the question is: given recent innovations with WASM, *are we Electron yet*?
|
2018-08-26 22:16:42 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
No, not really.
|
2018-08-26 22:16:42 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
Instead, **what would it take to get to a point where we can skip Javascript in Electron apps?**
|
2018-08-26 22:16:42 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
# Setting the Stage
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
Truth is, WASM/Webassembly is a pretty new technology and I'm generally unfamiliar with the tools.
|
|
|
|
There may already be solutions to the issues I discuss, but I'm totally unaware of them,
|
|
|
|
so I'm going to try and organize what I know exists.
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
I should also mention that the content and things I'm talking about here are not intended to be prescriptive,
|
|
|
|
but more "if someone else is interested, where should you start?" *I expect everything in this post to be irrelevant
|
|
|
|
within two months.* Even over the course of writing this, [a blog post](https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/)
|
|
|
|
was invalidated because [upstream changes](https://github.com/WebAssembly/binaryen/pull/1642)
|
|
|
|
broke [a Rust tool](https://github.com/rustwasm/wasm-bindgen/pull/787) that ultimately
|
|
|
|
[forced changes in the blog post](https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/#comment-477).
|
|
|
|
**And all that happened within the span of a week.** Things are moving quickly.
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
I'll also note that we're going to skip [asm.js] and [emscripten]. Truth be told, I couldn't get either of these
|
|
|
|
to produce anything, and so I'm just going to say [here be dragons.](https://en.wikipedia.org/wiki/Here_be_dragons)
|
|
|
|
Everything I'm discussing here is using the `wasm32-unknown-unknown` target.
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
And the code that I *did* get running is available [over here](https://github.com/bspeice/isomorphic_rust).
|
|
|
|
Feel free to use that as a starting point, but I'm mostly including the link as a reference point for the things
|
|
|
|
that do and don't work.
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
# An Example Running Application
|
|
|
|
|
|
|
|
So, I did *technically* get a running application:
|
|
|
|
|
|
|
|
![Electron app using WASM](/assets/images/2018-09-08-electron-percy-wasm.png)
|
|
|
|
|
|
|
|
...which you can also try out if you want to:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
git clone https://github.com/bspeice/isomorphic_rust.git
|
|
|
|
cd isomorphic_rust/percy
|
|
|
|
yarn install && yarn start
|
2018-08-27 00:20:49 -04:00
|
|
|
```
|
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
...but I really wouldn't use this as a "high quality" starting point. It's mostly just there
|
|
|
|
to prove that this is possible in the first place. And that's something to be proud of!
|
|
|
|
There's a huge amount of engineering that went into showing a window with the text "It's alive!".
|
|
|
|
|
|
|
|
There's also a huge number of issues under the hood that prevent me from recommending anyone
|
|
|
|
try using Electron and WASM at the moment, and I think that's the more important thing to discuss.
|
|
|
|
|
|
|
|
# Issues:
|
|
|
|
|
|
|
|
- Have to use wasm-bindgen so symbols get exported and are usable
|
|
|
|
- Have to use webpack/babel after bindgen so we can compile to something that's usable in a browser
|
|
|
|
- yew doesn't require wasm_bindgen, but doesn't link via webpack (env module) - think this is a stdweb issue
|
|
|
|
- Electron forces us to deal with MIME types - open webpack issue
|
|
|
|
- Incompatible low-level utilities - js-sys exists, but very fragmented with web-sys, stdweb, percy-webapis
|
2018-09-09 13:08:38 -04:00
|
|
|
- Can't include Cargo.lock so wasm-bindgen-cli is updated:
|
2018-09-09 01:02:58 -04:00
|
|
|
error: failed to extract wasm-bindgen custom sections
|
|
|
|
caused by:
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
it looks like the Rust project used to create this wasm file was linked against
|
|
|
|
a different version of wasm-bindgen than this binary:
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
rust wasm file: 0.2.21
|
|
|
|
this binary: 0.2.17
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
Currently the bindgen format is unstable enough that these two version must
|
|
|
|
exactly match, so it's required that these two version are kept in sync by
|
|
|
|
either updating the wasm-bindgen dependency or this binary. You should be able
|
|
|
|
to update the wasm-bindgen dependency with:
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
cargo update -p wasm-bindgen
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
or you can update the binary with
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
cargo install -f wasm-bindgen-cli
|
2018-08-27 00:20:49 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
if this warning fails to go away though and you're not sure what to do feel free
|
|
|
|
to open an issue at https://github.com/rustwasm/wasm-bindgen/issues!
|
2018-08-26 22:16:42 -04:00
|
|
|
|
2018-09-09 01:02:58 -04:00
|
|
|
error Command failed with exit code 1.
|
|
|
|
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
|
2018-08-26 22:16:42 -04:00
|
|
|
|
2018-09-09 13:08:38 -04:00
|
|
|
- Things I didn't try: wasm-pack to publish to NPM or local registry and pull down from there, static file server in Electron
|
|
|
|
|
2018-08-27 00:20:49 -04:00
|
|
|
[wxwidgets]: https://wxwidgets.org/
|
|
|
|
[libui-rs]: https://github.com/LeoTindall/libui-rs/
|
|
|
|
[electron]: https://electronjs.org/
|
|
|
|
[babel]: https://github.com/babel/babel
|
|
|
|
[conrod]: https://github.com/PistonDevelopers/conrod
|
|
|
|
[wxRust]: https://github.com/kenz-gelsoft/wxRust
|
|
|
|
[wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen
|
|
|
|
[js-sys]: https://crates.io/crates/js-sys
|
|
|
|
[percy-webapis]: https://crates.io/crates/percy-webapis
|
|
|
|
[stdweb]: https://crates.io/crates/stdweb
|
|
|
|
[web-sys]: https://crates.io/crates/web-sys
|
|
|
|
[percy]: https://chinedufn.github.io/percy/
|
|
|
|
[virtual-dom-rs]: https://crates.io/crates/virtual-dom-rs
|
|
|
|
[yew]: https://github.com/DenisKolodin/yew
|
|
|
|
[react]: https://reactjs.org/
|
|
|
|
[elm]: http://elm-lang.org/
|
|
|
|
[wasm-pack]: https://github.com/rustwasm/wasm-pack
|
|
|
|
[cargo-web]: https://github.com/koute/cargo-web
|
|
|
|
[percy-test]: https://github.com/chinedufn/percy/tree/master/examples/unit-testing-components
|
|
|
|
[asm.js]: http://asmjs.org/
|
|
|
|
[emscripten]: https://kripken.github.io/emscripten-site/
|
|
|
|
[gulpjs]: https://gulpjs.com/
|
|
|
|
[typescript]: https://www.typescriptlang.org/
|
|
|
|
[vuejs]: https://vuejs.org/
|