In this lesson we are going to setup a project from scratch by introducing the JavaScript snippet to load a WebAssembly module. We demonstrate two different ways and showcase the benefit of the streaming solution. Once the module is loaded we can invoke a function previously exported from our Rust code.
Instructor: [00:00] Use Cargo.new to create a new project called utils. Use --lib to declare that it's going to be a library. Next, we need to change the create type to cdylib in Cargo.toml. This has an impact on how things are linked together during compilation.
[00:17] We're now ready to write our first lines of Rust code. Let's get right into it, and create a public function, addOne. The extern keyword is needed to create an interface so that this function can be invoked from other languages.
[00:32] The function accepts a value X, which is an unsigned integer, which is incremented by one and returned. In addition, we need to add a @nomangle annotation to tell the Rust compiler not to mangle the name of this function.
[00:48] Next up, we can use Cargo.build to compile our utils library, targeting WebAssembly. After that, we can run wasm.gc, and output it to utils.gc.wasm in the current directory. Next up, we need to load it somehow. Therefore, we're going to create an index.html file and open a script tag.
[01:10] To load a WebAssembly module, we can fetch it, convert the response to an array buffer, instantiate the result, and then use the WASM module. It has an instance with export, including our addOne function. We can invoke the function and append the result to the DOM.
[01:47] Let's give this a try. We start our web server running HTTP. Once we open a site in the browser, we can see the result. Awesome. Here, you can see that our addOne function printed out the result of adding two plus one.
[02:02] There is one more improvement, though. In the current implementation, we fetch the entire WASM file before we instantiate it. Using instantiate streaming instead, we can stream, compile, and instantiate a WebAssembly module in one go.
[02:17] Especially on slow connections, this can speed up the time to execution a lot. We reload and review the result. Worked like a charm. Be aware, instantiate streaming requires that our WASM file must be served through the content type, application/wasm. Fortunately, our HTTP server already does so.
Hi Nik,
When I run http
(from the utils directory) in my terminal, this prompt is returned:
http: error: the following arguments are required: URL
When I run ```http url``, I get an error:
http: error: ConnectionError: HTTPConnectionPool(host='url', port=80): Max retries exceeded with url: / (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x101bff518>: Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known',)) while doing GET request to URL: http://url/
What would be the best way to troubleshoot this issue?
Thanks so much :-)
@Juliette you're not invoking rust http server, your http
is most likely an alias for the httpie client. Try this: ~/.cargo/bin/http
Cargo.toml:
... [lib] path = "src/lib.rs" crate-type = ["cdylib"]
Without 'path' variable cargo dont produce utils.wasm file in target/wasw32-unknown-unknown directory
Thank you @Mirza! I'm going to give that a try tomorrow after my first cup of coffee or so. Cheers:-)
Thanks for helping @Mirza
FYI I needed to prefix my build commands with rustup run nightly cargo build ...
in order to avoid crate errors and a suggestion that wasm32-unknown-unknown
target may not be installed.
WebAssembly.instantiateStreaming
is not supported in Safari, and either in Safari iOS, just in case someone like me is going to wonder why the results are different in Chrome and Safari: https://caniuse.com/#search=instantiateStreaming
I don't have an alias for http, command not found: http
also ~/.cargo/bin/http
doesn't exist, is there a way to install it?
@Steve totally, just pinged the Egghead team to fix it. thx!