Skip to content

Commit fbb979b

Browse files
author
dave horner
committed
build(dev): migrate to Webpack 5, async WASM, remove stdweb, update Svelte loader config, and fix example integration
1 parent baf8d21 commit fbb979b

File tree

12 files changed

+148
-78
lines changed

12 files changed

+148
-78
lines changed

README.md

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,50 @@ The examples in this crate are hosted online: [div-rs Examples](https://div.padd
2727

2828
Have a look at the code in example directory. The best way is to clone the repository and run it locally, so you can play around with the code.
2929

30-
You need npm, webpack, and wasm-pack for the examples to run on your machine.
31-
```
32-
git clone https://github.com/jakmeier/div-rs.git
33-
cd div-rs/examples/www;
34-
npm run build;
35-
npm run start;
30+
31+
## Requirements (2025+)
32+
33+
You need Node.js (16+ recommended), npm, and [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/) for the examples to run on your machine.
34+
35+
**This project now uses Webpack 5 for modern WebAssembly support.**
36+
37+
### Setup and Usage
38+
39+
1. Clone the repository:
40+
```sh
41+
git clone https://github.com/jakmeier/div-rs.git
42+
cd div-rs/examples/www
43+
```
44+
2. Install dependencies (this will install Webpack 5 and all required loaders/plugins):
45+
```sh
46+
npm install
47+
```
48+
3. Build all Rust WASM examples and bundle with Webpack:
49+
```sh
50+
npm run build
51+
```
52+
4. Start the development server:
53+
```sh
54+
npm start
55+
```
56+
5. Open your browser to the address shown in the terminal (usually http://localhost:8080).
57+
58+
### Cleaning builds
59+
60+
To clean all Rust and JS build artifacts:
61+
```sh
62+
npm run clean
3663
```
3764

65+
### Notable Changes (2025)
66+
67+
- **Webpack 5 migration:** The project now uses Webpack 5 for native async WebAssembly support. All config and dependencies have been updated.
68+
- **No more stdweb:** All examples now use `web-sys`, `wasm-bindgen`, and (where needed) `gloo-timers` for browser interop. `stdweb` is no longer supported.
69+
- **Svelte loader:** The Webpack config now includes `resolve.conditionNames` for Svelte 3+ compatibility.
70+
- **CopyWebpackPlugin:** Updated to use the new `patterns` API.
71+
72+
If you see WASM loader or Svelte warnings, make sure you have the latest dependencies and configs as above.
73+
3874
## Origin and Motivation
3975
My motivation to create Div was to leverage HTML + CSS when using Rust to create games for a browser.
4076
Prior to this, the only way I knew how to do a GUI easily (in Rust running on the browser) was to render everything through general-purpose GUI crates with a WebGL backend. This seemed a bit wasteful to me, as the browser already has excellent built-in support for GUIs.

examples/hello_svelte/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ pub fn main() {
1414
const H: u32 = 500;
1515
let class = div::JsClass::preregistered("MyComponent")
1616
.expect("JS class Test has not been registered properly");
17-
div::from_js_class(X, Y, W, H, class).unwrap();
17+
div::from_js_class(X as i32, Y as i32, W, H, class).unwrap();
1818

1919
/* Alternative that loads classes from a separate JS file instead of registering in the JS code. */
2020
// let future = async {
@@ -31,6 +31,5 @@ pub fn set_panic_hook() {
3131
//
3232
// For more details see
3333
// https://github.com/rustwasm/console_error_panic_hook#readme
34-
#[cfg(feature = "console_error_panic_hook")]
35-
console_error_panic_hook::set_once();
34+
// console_error_panic_hook::set_once();
3635
}

examples/reposition/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ edition = "2018"
88
[lib]
99
crate-type = ["cdylib", "rlib"]
1010

11+
1112
[dependencies]
1213
div = { path = "../../" }
1314
wasm-bindgen = "0.2"
14-
stdweb = "0.4"
1515

1616
[dependencies.web-sys]
1717
version = "0.3"
@@ -22,4 +22,6 @@ features = [
2222
"Window",
2323
"HtmlScriptElement",
2424
"HtmlHeadElement",
25+
"Event",
26+
"KeyboardEvent",
2527
]

examples/reposition/src/lib.rs

Lines changed: 44 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use stdweb::js;
2-
use stdweb::traits::*;
3-
use stdweb::web::event::KeyDownEvent;
1+
use wasm_bindgen::JsCast;
2+
use web_sys::window;
43
use wasm_bindgen::prelude::*;
54

65
/**
@@ -56,42 +55,51 @@ pub fn main() {
5655
let mut f = 1.0;
5756
let mut af = 1.0;
5857

59-
// We are using webstd here to make things easy.
60-
// Listen to arrow key to move and reposition all div
61-
stdweb::web::document().add_event_listener(move |e: KeyDownEvent| {
62-
match e.key().as_str() {
63-
"ArrowUp" => y = y.saturating_sub(10),
64-
"ArrowDown" => y += 10,
65-
"ArrowLeft" => x = x.saturating_sub(10),
66-
"ArrowRight" => x += 10,
67-
"+" => f *= 1.5,
68-
"-" => f /= 1.5,
58+
// Listen to keydown events to move and reposition all divs
59+
let closure = Closure::wrap(Box::new(move |event: web_sys::Event| {
60+
let keyboard_event = event.dyn_ref::<web_sys::KeyboardEvent>();
61+
if let Some(e) = keyboard_event {
62+
let key = e.key();
63+
match key.as_str() {
64+
"ArrowUp" => y = y.saturating_sub(10),
65+
"ArrowDown" => y += 10,
66+
"ArrowLeft" => x = x.saturating_sub(10),
67+
"ArrowRight" => x += 10,
68+
"+" => f *= 1.5,
69+
"-" => f /= 1.5,
6970

70-
"w" => ay = ay.saturating_sub(10),
71-
"a" => ax = ax.saturating_sub(10),
72-
"s" => ay += 10,
73-
"d" => ax += 10,
74-
"1" => af *= 1.5,
75-
"2" => af /= 1.5,
71+
"w" => ay = ay.saturating_sub(10),
72+
"a" => ax = ax.saturating_sub(10),
73+
"s" => ay += 10,
74+
"d" => ax += 10,
75+
"1" => af *= 1.5,
76+
"2" => af /= 1.5,
7677

77-
key => {
78-
js! { @(no_return) console.log("pressed " + @{key}); };
79-
return;
78+
_ => {
79+
web_sys::console::log_1(&format!("pressed {}", key).into());
80+
return;
81+
}
8082
}
83+
div::reposition(x, y).unwrap();
84+
let w = f * w as f32;
85+
let h = f * h as f32;
86+
div::resize(w as u32, h as u32).unwrap();
87+
88+
let aw = af * aw as f32;
89+
let ah = af * ah as f32;
90+
pane_a
91+
.reposition_and_resize(ax, ay, aw as u32, ah as u32)
92+
.unwrap();
93+
// Same as
94+
// pane_a.reposition(ax,ay).unwrap();
95+
// pane_a.resize(aw as u32, ah as u32).unwrap();
96+
// but avoids extra redraw of div
8197
}
82-
div::reposition(x, y).unwrap();
83-
let w = f * w as f32;
84-
let h = f * h as f32;
85-
div::resize(w as u32, h as u32).unwrap();
98+
}) as Box<dyn FnMut(_)>);
8699

87-
let aw = af * aw as f32;
88-
let ah = af * ah as f32;
89-
pane_a
90-
.reposition_and_resize(ax, ay, aw as u32, ah as u32)
91-
.unwrap();
92-
// Same as
93-
// pane_a.reposition(ax,ay).unwrap();
94-
// pane_a.resize(aw as u32, ah as u32).unwrap();
95-
// but avoids extra redraw of div
96-
});
100+
window()
101+
.unwrap()
102+
.add_event_listener_with_callback("keydown", closure.as_ref().unchecked_ref())
103+
.unwrap();
104+
closure.forget();
97105
}

examples/styled/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ edition = "2018"
88
[lib]
99
crate-type = ["cdylib", "rlib"]
1010

11+
1112
[dependencies]
1213
div = { path = "../../" }
1314
wasm-bindgen = "0.2"
14-
stdweb = "0.4"
1515

1616
[dependencies.web-sys]
1717
version = "0.3"
@@ -22,4 +22,5 @@ features = [
2222
"Window",
2323
"HtmlScriptElement",
2424
"HtmlHeadElement",
25+
"HtmlStyleElement",
2526
]

examples/styled/src/lib.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
* Usually we would have your styles served from a .css or inside a svelte component.
55
* But if you want to, you can also apply CSS to a pane from within Rust.
66
*/
7-
use stdweb::web::*;
7+
use wasm_bindgen::JsCast;
8+
use web_sys::{window, HtmlStyleElement};
89
use wasm_bindgen::prelude::*;
910

1011
#[wasm_bindgen(start)]
@@ -47,9 +48,14 @@ pub fn main() {
4748
// Small helper function, only for the example. Uses stdweb, DIV-RS does not really help you with this part of CSS.
4849
// It is not recommended to add classes like this but it is useful here to keep everything in a single file.
4950
fn add_document_styles(css: &str) {
50-
let head = document().head().unwrap();
51-
let style = document().create_element("style").unwrap();
52-
style.set_attribute("type", "text/css").unwrap();
53-
style.append_html(css).unwrap();
54-
head.append_child(&style);
51+
let document = window().unwrap().document().unwrap();
52+
let head = document.head().unwrap();
53+
let style = document
54+
.create_element("style")
55+
.unwrap()
56+
.dyn_into::<HtmlStyleElement>()
57+
.unwrap();
58+
style.set_type("text/css");
59+
style.set_inner_html(css);
60+
head.append_child(&style).unwrap();
5561
}

examples/toggle/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"]
1111
[dependencies]
1212
div = { path = "../../" }
1313
wasm-bindgen = "0.2"
14-
stdweb = "0.4"
14+
gloo-timers = "0.2"
1515

1616
[dependencies.web-sys]
1717
version = "0.3"

examples/toggle/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use div::DivHandle;
2-
use stdweb::web::set_timeout;
2+
use gloo_timers::callback::Timeout;
33

44
use wasm_bindgen::prelude::*;
55

@@ -33,8 +33,7 @@ pub fn main() {
3333
fn toggle(a: DivHandle, b: DivHandle) {
3434
a.show().expect("Error");
3535
b.hide().expect("Error");
36-
let closure = move || {
36+
Timeout::new(1000, move || {
3737
toggle(b, a);
38-
};
39-
set_timeout(closure, 1000);
38+
}).forget();
4039
}

examples/www/index.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
import "./styles.css";
99

10-
import * as hello_world from "../hello_world/pkg/hello_world_bg.wasm";
11-
import * as reposition from "../reposition/pkg/reposition_bg.wasm";
12-
import * as styled from "../styled/pkg/styled_bg.wasm";
13-
import * as toggle from "../toggle/pkg/toggle_bg.wasm";
1410

11+
import * as hello_world from "../hello_world/pkg/hello_world.js";
12+
import * as reposition from "../reposition/pkg/reposition.js";
13+
import * as styled from "../styled/pkg/styled.js";
14+
import * as toggle from "../toggle/pkg/toggle.js";
1515

16-
import * as hello_svelte from "../hello_svelte/pkg/hello_svelte_bg.wasm";
16+
import * as hello_svelte from "../hello_svelte/pkg/hello_svelte.js";
1717
import { register_svelte_component, init_div_rs } from "../../div-rs.js";
1818
import MyComponent from "../hello_svelte/src/MyComponent.svelte";
1919

@@ -75,6 +75,7 @@ examples.push(example(
7575

7676
loadExampleSelection(examples);
7777

78+
7879
let params = new URLSearchParams(location.search);
7980
let displayedExample = params.get('example');
8081

examples/www/package.json

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,20 @@
77
"create-wasm-app": ".bin/create-wasm-app.js"
88
},
99
"scripts": {
10-
"build": "wasm-pack build ../hello_svelte; wasm-pack build ../hello_world; wasm-pack build ../reposition/; wasm-pack build ../styled/; wasm-pack build ../toggle; webpack --config webpack.config.js",
10+
"clean:wasm": "cargo clean --manifest-path ../hello_svelte/Cargo.toml && cargo clean --manifest-path ../hello_world/Cargo.toml && cargo clean --manifest-path ../reposition/Cargo.toml && cargo clean --manifest-path ../styled/Cargo.toml && cargo clean --manifest-path ../toggle/Cargo.toml",
11+
"clean:js": "rimraf dist pkg",
12+
"clean": "npm-run-all clean:wasm clean:js",
13+
"build:wasm": "run-s build:hello_svelte build:hello_world build:reposition build:styled build:toggle",
14+
"build:hello_svelte": "wasm-pack build ../hello_svelte",
15+
"build:hello_world": "wasm-pack build ../hello_world",
16+
"build:reposition": "wasm-pack build ../reposition",
17+
"build:styled": "wasm-pack build ../styled",
18+
"build:toggle": "wasm-pack build ../toggle",
19+
"build": "npm-run-all build:wasm build:webpack",
20+
"build:webpack": "webpack --config webpack.config.js",
1121
"start": "webpack-dev-server",
12-
"release": "wasm-pack build ../hello_svelte; wasm-pack build ../hello_world; wasm-pack build ../reposition/; wasm-pack build ../styled/; wasm-pack build ../toggle; webpack --config webpack.prod.js"
22+
"release": "npm-run-all build:wasm release:webpack",
23+
"release:webpack": "webpack --config webpack.prod.js"
1324
},
1425
"repository": {
1526
"type": "git",
@@ -35,14 +46,15 @@
3546
"toggle": "file:../toggle/pkg/"
3647
},
3748
"devDependencies": {
38-
"copy-webpack-plugin": "^5.0.0",
39-
"css-loader": "^4.3.0",
40-
"style-loader": "^1.2.1",
41-
"svelte": "^3.29.0",
42-
"svelte-loader": "^2.13.6",
43-
"webpack": "^4.29.3",
44-
"webpack-cli": "^3.1.0",
45-
"webpack-dev-server": "^3.1.5",
46-
"webpack-merge": "^5.2.0"
49+
"copy-webpack-plugin": "^11.0.0",
50+
"css-loader": "^6.8.1",
51+
"npm-run-all": "^4.1.5",
52+
"style-loader": "^3.3.4",
53+
"svelte": "^3.59.2",
54+
"svelte-loader": "^3.1.6",
55+
"webpack": "^5.88.2",
56+
"webpack-cli": "^5.1.4",
57+
"webpack-dev-server": "^4.15.1",
58+
"webpack-merge": "^5.10.0"
4759
}
4860
}

0 commit comments

Comments
 (0)