In this tutorial, we’ll guide you through the step-by-step process of deploying a Rust WebAssembly (WASM) app on GitHub Pages. The final website will consist of a JavaScript frontend that utilizes WASM, generated from Rust code.
The project we’ll use is called lp, a logical operation language that I created earlier. We won’t delve into the implementation details; instead, our focus will be on incorporating WASM into an existing Rust project.
TL;DR
wasm-bindgengenerates.wasmand glue JS files.wasm-packgenerates JS files intended to be imported from JS usingwasm-bindgen.wasm-packcan generate files suitable for bundlers likewebpack.
wasm-pack without bundler
The project structure looks like this, and the entire code is available on GitHub.
| |
Let’s begin by adding wasm-bindgen, a tool that handles the interaction between Rust and JavaScript, to the Cargo.toml file:
| |
Along with adding wasm-bindgen as a dependency, the [lib] section is also added, specifying the crate-type to generate WASM code.
In lib.rs, we’ll add #[wasm_bindgen] attribute to a struct and impl block, indicating these Rust codes should be callable from JavaScript.
| |
To build the file for the WASM app, we’ll use wasm-pack, a tool covering from building Rust to generating a package to be published to npm, though We won’t publish our package in this post. Install wasm-pack CLI tool by running cargo install wasm-pack and execute the following command:
| |
Some files will be produced in the www/pkg directory:
lp.js: an interface file to be imported from other JavaScript files.lp_bg.wasm: a WASM file that includes the implementation converted fromlib.rs..ts.dincludes type definitions.
The --no-pack option stops the creation of package.json, which is not necessary in our example.
HTML and JavaScript to Import WASM
Finally, let’s add index.html and index.js:
| |
| |
The crucial part here is the initial part of index.js, where the initialization function and Rust struct are imported. init() is an asynchronous function that should be called with await.
We can test this app with a local HTTP server, like miniserve www --index "index.html" -p 8080.
Before pushing it to GitHub, don’t forget to include the www/pkg by deleting www/pkg/.gitignore. See the Creating a GitHub Pages site to set up your repository. If you leave the default options, the app will be accessed at https://username.github.io/lp/www/.
wasm-pack and webpack
While the previous scenario works properly, there is another way to incorporate Rust WASM into JavaScript: using module bundlers. Module bundlers like webpack can be used to integrate multiple files into a single file.
While using webpack makes the process a little more complicated, it’s more practical. Let’s take a quick look at how to use it with a Rust WASM app.
wasm-pack has a --target bundler option to generate files suitable for use with a bundler. The build command will be like:
| |
Next, go to the www directory and run the following command to register the pkg as a dependency:
| |
You will see package.json created. Add some npm packages for webpack:
| |
To configure webpack, create webpack.config.js as follows:
| |
For convenience, you can add some scripts to package.json:
| |
The index.html remains the same, and index.js needs a slight modification. Now lp is an npm package in the node_modules directory, so it is imported like this:
| |
Run npm run serve to launch a web server and open http://localhost:8080. Before pushing it, make sure to execute npm run build to generate files (.html, .js, and .wasm) in www/dist that should be deployed to GitHub. The final output would be like https://momori256.github.io/lip/lp/www/dist/
Conclusion
We have covered how to leverage wasm-bindgen, wasm-pack, and webpack to integrate Rust with a JavaScript frontend. For further exploration and comprehensive details, consider referring to the following resources:
- Deploying Rust and WebAssembly: The
wasm-packdocument about possible build targets. - Compiling from Rust to WebAssembly: A tutorial for building a
hello worldWASM app. - JavaScript to Rust and Back Again: A wasm-bindgen Tale: An article about what
wasm-bindgenis and how it works. - Hello wasm-pack!: The purpose of
wasm-packand the explanation of its process.