Wasm rust: Difference between revisions
Line 77: | Line 77: | ||
And here is the file structure I used in this case where www is the node project and pkg contains the rust assembly<br> | And here is the file structure I used in this case where www is the node project and pkg contains the rust assembly<br> | ||
[[File:Rust wasm file structure.png]] | [[File:Rust wasm file structure.png]] | ||
=Running Going Forward= | |||
All that out of the way the next thing is to look at messing with the dom. Don't forget to get changes to your rust you need to run webpack. So in the web app you need to do | |||
<syntaxhighlight lang="bash"> | |||
wasm-pack build | |||
npm run start | |||
</syntaxhighlight> | |||
=An example= | |||
This is taken from Ben Lovy on dev.io and demonstrates enough to get started. First we need to add the dependency on web-sys to the toml. | |||
<syntaxhighlight lang="cargo"> | |||
[dependencies] | |||
wasm-bindgen = "0.2" | |||
[dependencies.web-sys] | |||
version = "0.3" | |||
features = [ | |||
"Attr", | |||
"CanvasRenderingContext2d", | |||
"Document", | |||
"Element", | |||
"Event", | |||
"EventTarget", | |||
"HtmlCanvasElement", | |||
"HtmlElement", | |||
"HtmlInputElement", | |||
"Node", | |||
"Text", | |||
"Window", | |||
] | |||
</syntaxhighlight> | |||
And now the code | |||
<syntaxhighlight lang="rust"> | |||
use wasm_bindgen::prelude::*; | |||
use web_sys::{Document, HtmlElement}; | |||
#[wasm_bindgen] | |||
pub fn run() { | |||
// get window/document/body | |||
let window = web_sys::window().expect("Could not get window"); | |||
let document = window.document().expect("Could not get document"); | |||
let body = document.body().expect("Could not get body"); | |||
mount_app(&document, &body); | |||
} | |||
fn mount_app(document: &Document, body: &HtmlElement) { | |||
mount_title(&document, &body); | |||
} | |||
// Create a title | |||
fn mount_title(document: &Document, body: &HtmlElement) { | |||
// create title element | |||
let title = document | |||
.create_element("h1") | |||
.expect("Could not create element"); | |||
let title_text = document.create_text_node("DOT"); // always succeeds | |||
title | |||
.append_child(&title_text) | |||
.expect("Could not append child to title"); | |||
// append to body | |||
body.append_child(&title) | |||
.expect("Could not append title to body"); | |||
} | |||
</syntaxhighlight> |
Revision as of 00:11, 29 September 2024
Introduction
Getting started was not easy. This was more due to the npm half of the deal.
create-wasm-app
There is something called create-wasm-app which creates a template for rust. When I used it I could not get it to work. To fix this I had to first install the app locally and the create a package.json with a dependency
# Install
npm install -g create-wasm-app
# List where it is
npm list -g
// Mine was /home/iwiseman/.nvm/versions/node/v22.8.0/lib
Now make the package.json
{
"dependencies": {
"create-wasm-app": "/home/iwiseman/.nvm/versions/node/v22.8.0/lib/node_modules/create-wasm-app"
}
}
Now create the app
npm init wasm-app www
Next we try and run the code with
npm run start
And we get the following error
Googling as we do we find we can add a flag to Nodejs to use legacy ssl
...
"scripts": {
"build": "webpack --config webpack.config.js",
"start": "NODE_OPTIONS=--openssl-legacy-provider webpack-dev-server"
},
...
Now we go http://localhost:8081/
Clearly anything around ssl and legacy are perhaps not a way forward so I updated packages to latest
"devDependencies": {
"hello-wasm-pack": "^0.1.0",
"webpack": "^5.95.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.1.0",
"copy-webpack-plugin": "^12.0.2"
}
This updates from webpack 4 to 5 and breaks the plugin. First off the CopyWebpackPlugin format has changed from
plugins: [
new CopyWebpackPlugin(['index.html'])
],
To
plugins: [
new CopyWebpackPlugin({
patterns: ["index.html"],
}),
],
Now we have fixed that, lets hit that start button. And the result is
Well this was easy to fix. You google The module seem to be a WebAssembly module and hey presto the answer is found. I struggle to read documents as a general rule but looking at the error webpack produced in the image, it is pretty clear already what to do. I wonder if my frustration with reading has closed my mind to reading. And there is not point in having a mind if you don't change it. On with the answer in webpack.config.js.
...
module.exports = {
experiments: {
asyncWebAssembly: true,
},
...
And here is the file structure I used in this case where www is the node project and pkg contains the rust assembly
Running Going Forward
All that out of the way the next thing is to look at messing with the dom. Don't forget to get changes to your rust you need to run webpack. So in the web app you need to do
wasm-pack build
npm run start
An example
This is taken from Ben Lovy on dev.io and demonstrates enough to get started. First we need to add the dependency on web-sys to the toml.
[dependencies]
wasm-bindgen = "0.2"
[dependencies.web-sys]
version = "0.3"
features = [
"Attr",
"CanvasRenderingContext2d",
"Document",
"Element",
"Event",
"EventTarget",
"HtmlCanvasElement",
"HtmlElement",
"HtmlInputElement",
"Node",
"Text",
"Window",
]
And now the code
use wasm_bindgen::prelude::*;
use web_sys::{Document, HtmlElement};
#[wasm_bindgen]
pub fn run() {
// get window/document/body
let window = web_sys::window().expect("Could not get window");
let document = window.document().expect("Could not get document");
let body = document.body().expect("Could not get body");
mount_app(&document, &body);
}
fn mount_app(document: &Document, body: &HtmlElement) {
mount_title(&document, &body);
}
// Create a title
fn mount_title(document: &Document, body: &HtmlElement) {
// create title element
let title = document
.create_element("h1")
.expect("Could not create element");
let title_text = document.create_text_node("DOT"); // always succeeds
title
.append_child(&title_text)
.expect("Could not append child to title");
// append to body
body.append_child(&title)
.expect("Could not append title to body");
}