|
|
|
CroftSoft
/
Library
/
Tutorials
Rust-webpack Project Setup
2023 Jul 23 Sun
David Wallace Croft
Contents
Links
In recommended reading order
Background
In 2022, I read the book published in that same year
Game Development with Rust & WebAssembly
by Eric Smith which uses the
rust-webpack-template.
The author speculated that the rust-webpack-template
might be updated in the near future so some instructions might need to be
adjusted as time goes on. While writing a
tutorial checklist
on how to set up a project using the rust-webpack-template,
I noted that the GitHub project for it had not been updated in three years.
I ran into an issue during development of a project that was initialized using
the rust-webpack-template that I suspected could be resolved by reading through
the
webpack
documentation.
The version of webpack that the rust-webpack-template supported was so old that
I had trouble finding documentation for it. Also, the latest major version of
webpack had changed enough that it did not work with the rust-webpack-template
setup.
After a fair amount of effort, much experimentation, and some reading of the
webpack documentation, I was able to migrate
my Rust project
that was set up using the rust-webpack-template into something that
is now compatible with a recent major version of webpack.
This also resolved my original development issue.
This tutorial checklist captures that knowledge in a repeatable step-by-step
fashion and should be considered as an updated alternative to using the
rust-webpack-template.
Project Setup
-
Start by following the instructions in the
Rust Project Setup
-
Install
node.js
-
This will also install Node Package Manager (npm)
-
Update your project root directory .gitignore file to include the following:
/dist
/pkg
/target
/wasm-pack.log
node_modules
-
Append the following to your Cargo.toml file:
[dependencies]
anyhow = "1.0.72"
console_error_panic_hook = "0.1.7"
futures = "0.3.28"
js-sys = "0.3.64"
wasm-bindgen = "0.2.87"
wasm-bindgen-futures = "0.4.37"
[dependencies.web-sys]
features = [
"CanvasRenderingContext2d",
"Document",
"HtmlCanvasElement",
"HtmlDivElement",
"Window",
"console",
]
version = "0.3.64"
[dev-dependencies]
wasm-bindgen-test = "0.3.37"
[lib]
crate-type = ["cdylib"]
[profile.release]
lto = true
-
Delete src/main.rs and replace it with src/lib.rs:
use js_sys::Object;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::console;
use web_sys::window;
use web_sys::CanvasRenderingContext2d;
use web_sys::Document;
use web_sys::Element;
use web_sys::HtmlCanvasElement;
use web_sys::HtmlDivElement;
#[wasm_bindgen(start)]
pub fn main_js() -> Result<(), JsValue> {
console_error_panic_hook::set_once();
let document: Document = window().unwrap().document().unwrap();
hello_canvas(&document);
hello_console();
hello_div(&document);
Ok(())
}
fn hello_canvas(document: &Document) {
let element: Element = document.get_element_by_id("canvas").unwrap();
let html_canvas_element: HtmlCanvasElement = element.dyn_into().unwrap();
let object: Object = html_canvas_element.get_context("2d").unwrap().unwrap();
let canvas_context: CanvasRenderingContext2d = object.dyn_into().unwrap();
canvas_context.set_font("normal 14px serif");
canvas_context.stroke_text("Hello, Canvas!", 0.0, 14.0).unwrap();
}
fn hello_console() {
console::log_1(&JsValue::from_str("Hello, Console!"));
}
fn hello_div(document: &Document) {
let element: Element = document.get_element_by_id("div").unwrap();
let html_div_element: HtmlDivElement = element.dyn_into().unwrap();
html_div_element.insert_adjacent_text("afterbegin", "Hello, Div!").unwrap();
}
-
Make a single-line JavaScript file named js/entry-index.js:
import("../pkg/index.js").catch(console.error);
-
Make a static/index.html file:
<!DOCTYPE html>
<html>
<head>
<meta
charset="utf-8">
<title>
Project Name
</title>
</head>
<body>
<canvas
height="25"
id="canvas"
width="100">
</canvas>
<div
id="div">
</div>
<script
src="my-app.js">
</script>
</body>
</html>
-
Make a webpack.config.js file in your project root directory:
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
const WasmPackPlugin = require('@wasm-tool/wasm-pack-plugin');
module.exports = {
devServer: {
allowedHosts: ['localhost'],
client: {
logging: 'verbose',
overlay: true,
progress: true,
},
open: true,
static: false,
},
entry: {
index: './js/entry-index.js'
},
experiments: {
asyncWebAssembly: true,
},
mode: 'production',
output: {
filename: 'my-app.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new CopyPlugin([
path.resolve(__dirname, 'static')
]),
new WasmPackPlugin({
crateDirectory: __dirname,
}),
]
};
-
Make a package.json in your root directory:
{
"author": "My Name <my-example-address@example.com>",
"description": "My App description",
"devDependencies": {
"@wasm-tool/wasm-pack-plugin": "^1.7.0",
"@webpack-cli/serve": "^2.0.5",
"copy-webpack-plugin": "^5.1.2",
"rimraf": "^5.0.1",
"wasm-pack": "^0.12.1",
"webpack": "^5.88.2",
"webpack-dev-server": "^4.15.1"
},
"name": "my-app",
"scripts": {
"build": "rimraf dist pkg && webpack",
"start": "rimraf dist pkg && webpack serve",
"test": "cargo test && wasm-pack test --firefox --headless"
},
"version": "0.1.0"
}
-
Launch the project
npm install
npm start
© 2023
CroftSoft Inc
|
|
|
|
|
|