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-bindgen
generates.wasm
and glue JS files.wasm-pack
generates JS files intended to be imported from JS usingwasm-bindgen
.wasm-pack
can 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.d
includes 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-pack
document about possible build targets. - Compiling from Rust to WebAssembly: A tutorial for building a
hello world
WASM app. - JavaScript to Rust and Back Again: A wasm-bindgen Tale: An article about what
wasm-bindgen
is and how it works. - Hello wasm-pack!: The purpose of
wasm-pack
and the explanation of its process.