Skip to content

Wasm splitting in yew - #3932

Open
WorldSEnder wants to merge 11 commits into
yewstack:masterfrom
WorldSEnder:split-wasm
Open

Wasm splitting in yew#3932
WorldSEnder wants to merge 11 commits into
yewstack:masterfrom
WorldSEnder:split-wasm

Conversation

@WorldSEnder

Copy link
Copy Markdown
Member

Description

Add a way to split the wasm bundle in multiple components. This modifies the build process, and uses relocation information emitted by llvm to identify where to "split". There's a bit of glue code in yew to ensure that messages sent to the lazy component are processed and properties are passed along without additional cloning.

The main part of the solution lives in https://github.com/WorldSEnder/wasm-split-prototype as of now. This was implemented in collaboration with the maintainer of leptos.

Checklist

  • I have reviewed my own code
  • I have added examples

@WorldSEnder
WorldSEnder requested review from jstarry and ranile October 14, 2025 21:01
github-actions[bot]
github-actions Bot previously approved these changes Oct 14, 2025
@WorldSEnder

WorldSEnder commented Oct 14, 2025

Copy link
Copy Markdown
Member Author

The review pings are mostly because I think both of you will find this interesting, not necessarily as an invite to dig into the code and give meaningful suggestions for improvements (but feel free to if you have the time).

github-actions[bot]
github-actions Bot previously approved these changes Oct 16, 2025
@github-actions

github-actions Bot commented Oct 16, 2025

Copy link
Copy Markdown

Benchmark - core

Yew Master

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  2.404 ns      │ 3.666 ns      │ 2.41 ns       │ 2.576 ns      │ 100     │ 1000000000

Pull Request

vnode           fastest       │ slowest       │ median        │ mean          │ samples │ iters
╰─ vnode_clone  2.437 ns      │ 3.741 ns      │ 2.446 ns      │ 2.634 ns      │ 100     │ 1000000000

@github-actions

github-actions Bot commented Oct 16, 2025

Copy link
Copy Markdown

Benchmark - SSR

Yew Master

Details
Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 302.254 303.283 302.682 0.327
Hello World 10 467.579 493.424 479.426 10.716
Function Router 10 29999.886 30554.140 30308.760 177.854
Concurrent Task 10 1006.039 1007.850 1007.220 0.592
Many Providers 10 1012.792 1039.176 1024.699 10.377

Pull Request

Details
Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 346.748 359.973 348.179 4.145
Hello World 10 466.450 474.220 468.757 2.380
Function Router 10 29844.062 30167.181 29994.037 108.874
Concurrent Task 10 1005.848 1007.619 1006.943 0.545
Many Providers 10 1024.816 1087.372 1052.001 21.169

github-actions[bot]
github-actions Bot previously approved these changes Oct 22, 2025
@github-actions

github-actions Bot commented Oct 22, 2025

Copy link
Copy Markdown

Visit the preview URL for this PR (updated for commit 67ba59f):

https://yew-rs-api--pr3932-split-wasm-v3rbjdhv.web.app

(expires Wed, 02 Sep 2026 11:42:53 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Comment thread packages/yew/src/lazy.rs Outdated
github-actions[bot]
github-actions Bot previously approved these changes Mar 11, 2026
@github-actions

github-actions Bot commented Mar 11, 2026

Copy link
Copy Markdown

Size Comparison

Details
examples master (KB) pull request (KB) diff (KB) diff (%)
async_clock 100.399 100.531 +0.132 +0.131%
boids 165.096 154.980 -10.115 -6.127%
communication_child_to_parent 93.863 94.248 +0.385 +0.410%
communication_grandchild_with_grandparent 106.250 107.029 +0.779 +0.733%
communication_grandparent_to_grandchild 102.571 103.351 +0.779 +0.760%
communication_parent_to_child 91.252 91.628 +0.376 +0.412%
contexts 106.559 107.737 +1.179 +1.106%
counter 86.425 86.564 +0.140 +0.162%
counter_functional 88.559 88.689 +0.131 +0.148%
dyn_create_destroy_apps 90.325 90.456 +0.131 +0.145%
file_upload 98.734 98.871 +0.137 +0.138%
function_delayed_input 94.873 95.015 +0.142 +0.149%
function_memory_game 168.858 159.402 -9.456 -5.600%
function_router 398.718 402.395 +3.677 +0.922%
function_todomvc 165.253 155.527 -9.726 -5.885%
futures 236.113 236.245 +0.132 +0.056%
game_of_life 100.795 100.930 +0.135 +0.134%
immutable 258.946 263.450 +4.504 +1.739%
inner_html 80.935 81.066 +0.132 +0.163%
js_callback 110.006 110.902 +0.896 +0.815%
keyed_list 176.500 176.874 +0.374 +0.212%
mount_point 84.349 84.479 +0.131 +0.155%
nested_list 112.894 113.470 +0.576 +0.510%
node_refs 91.933 92.306 +0.373 +0.406%
password_strength 1766.239 1771.830 +5.591 +0.317%
portals 93.751 94.126 +0.375 +0.400%
router 364.950 367.792 +2.842 +0.779%
split-wasm N/A 768.602 N/A N/A
suspense 114.184 115.475 +1.291 +1.131%
timer 88.671 88.803 +0.132 +0.149%
timer_functional 99.674 100.049 +0.375 +0.376%
todomvc 142.158 131.631 -10.527 -7.405%
two_apps 86.329 86.469 +0.140 +0.162%
web_worker_fib 136.741 137.547 +0.806 +0.589%
web_worker_prime 186.834 187.627 +0.793 +0.424%
webgl 83.082 83.219 +0.137 +0.165%

⚠️ The following examples have changed their size significantly:

examples master (KB) pull request (KB) diff (KB) diff (%)
boids 165.096 154.980 -10.115 -6.127%
contexts 106.559 107.737 +1.179 +1.106%
function_memory_game 168.858 159.402 -9.456 -5.600%
function_todomvc 165.253 155.527 -9.726 -5.885%
immutable 258.946 263.450 +4.504 +1.739%
suspense 114.184 115.475 +1.291 +1.131%
todomvc 142.158 131.631 -10.527 -7.405%

github-actions[bot]
github-actions Bot previously approved these changes Mar 11, 2026
github-actions[bot]
github-actions Bot previously approved these changes Mar 11, 2026
@WorldSEnder

Copy link
Copy Markdown
Member Author

I want to say that having wasm split support would probably cut down the size of all these different bundles in the current "Yew.rs in Yew" push.

github-actions[bot]
github-actions Bot previously approved these changes Mar 11, 2026

@Madoshakalaka Madoshakalaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks really good now. I can't spot anything wrong.

can you suppress the warnings though?

split-wasm git:(split-wasm) ✗ ./build.sh
/home/maa/.cache/trunk/wasm-bindgen-0.2.114/wasm-bindgen
warning: function `start_now` is never used
   --> packages/yew/src/scheduler.rs:214:15
    |
214 | pub(crate) fn start_now() {
    |               ^^^^^^^^^
    |
    = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default

warning: `yew` (lib) generated 1 warning
    Finished `release` profile [optimized] target(s) in 0.11s
running wasm-bindgen
running wasm-opt
warning: unknown name subsection with id 3 at 25937
moving to dist dir

@Madoshakalaka

Copy link
Copy Markdown
Member

I want to say that having wasm split support would probably cut down the size of all these different bundles in the current "Yew.rs in Yew" push.

yeeaah

It'd be nice if you could add some wasm-split docs in the mdx files too. It will take a while for the rewrite to land anyway. I'll sync the docs there.

github-actions[bot]
github-actions Bot previously approved these changes Mar 17, 2026
Comment on lines +214 to +220
#[cfg(any(
test,
feature = "test",
not(target_arch = "wasm32"),
target_os = "wasi",
feature = "not_browser_env"
))]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this very unreadable. Unifying the entry points into the scheduler might make it more clear which target uses which loop.

The yield strategy in #4033 does not take the LOCK to prevent recursive re-entry, but duplicates code from here. This method is now basically only used in tests as a substitute for a sync flush (which should be fine). Nevertheless, I would try to clean this up in a follow up PR.

don't start fetching once per component, cache the vtable.
makes it possible to implement a helper macro without the user
pulling in an extra dependency and has tighter version requirements.
we accept the penalty of running a lot of lifecycle hooks twice:
once for the Lazy<_> component, once for the inner one, and just forward
messages and other things, instead of hacking around in Scope.
github-actions[bot]
github-actions Bot previously approved these changes Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants