In this tutorial, we do the computation on WASM and draw the canvas at Javascript.
I kind of confuse, where to do things exactly.
I thought we should do 'everything' on WASM / Rust part?
Is this (computation on WASM and draw the canvas at Javascript.) because of the limitation on wasm-bindgen? or that's the best practice? may I ask why?
What's the official resource to know what I can do and can't?
WebAssembly has no direct access to the DOM or any of the web and browser APIs available in JS. This is just how WASM is and is unlikely to change very soon.
To elaborate, WASM is just a portable format for executables/byte code that can be interpreted or compiled and optimized; it is not an operating system.
When you are running Rust compiled to WASM in your browser, then the browser is your host. It's no different from running Rust compiled to x64 assembly under Linux, for example, except that JavaScript does the heavy lifting and the interesting part, not system calls.
You probably wouldn't insist that we should do everything in x64 assembly and never reach for system calls, because that is the way to interact with the OS. Likewise, calling into JavaScript is how you interact with the browser. It's not a limitation of wasm-bindgen.
Based on the response, What I'm thinking right now is like "controller" - "view" separation. Where the logics will be in Rust/WASM, but the DOM manipulations stay in Javascript.
You can structure your app any way you want. The relationship between JavaScript and WebAssembly is completely independent of model-view-controller or any other architecture.
The only requirement is that in order for WebAssembly to interact with the outside world (the browser, in this case), it needs to somehow call the corresponding JavaScript functions.
The web-sys and js-sys crates have declarations for pretty much all the functions a normal JavaScript app would have access to, including things like DOM access, promises, and the fetch() API, so it's quite possible to write a whole web app in Rust compiled to WebAssembly. See the yew framework for an example.
Wasm is faster but can not talk to your browser. Javascript talks to your browser. Wasm and javascript talk to each other. So if you want you wasm to do something in the browser, your wasm has to tell javascript to do it.
You can make javascript functions to call your browser api's and you can call those functions from your wasm code. web-sys does this for you.
Thanks @Michael-F-Bryan for clarifying this.
So indeed these crates give us access to manipulate DOM.
I can see the cons manipulating the DOM from Rust/WASM is a bit harder, it terms of Developer Experience. But does it have a 'significant speed improvement' as well when we're doing manipulating DOM from Rust/WASM? like the intention of WASM itself?
The way things are implemented at the moment, WebAssembly needs to call JavaScript functions in order to manipulate the DOM, so it can't be faster than pure JS.
Your speed benefits mainly come from the amount of work you can do before touching the DOM. In the same ay that a React app will "render" cheap JavaScript objects so the framework can use fancy algorithms to do the smallest possible number of DOM changes, you can take a similar approach in WebAssembly.
However, I don't think UIs are where WebAssembly really shines. It'd be much smarter to use WebAssembly for something where performance and control over memory makes a massive difference like running a game, editing package logic (e.g. Lucid Charts), codecs, and so on. It's also useful for bringing native libraries to the browser without needing to rewrite them in JavaScript.
Things like the Component Model Proposal might be able to improve things because it'd let WebAssembly directly call into a browser's C++ code, but that proposal has been in the works for several years in different forms, so I wouldn't hold my breath.