Skip to content

feat: add yew-link crate for unified SSR/CSR data fetching#4027

Open
Madoshakalaka wants to merge 1 commit intomasterfrom
yew-link
Open

feat: add yew-link crate for unified SSR/CSR data fetching#4027
Madoshakalaka wants to merge 1 commit intomasterfrom
yew-link

Conversation

@Madoshakalaka
Copy link
Member

@Madoshakalaka Madoshakalaka commented Mar 1, 2026

Description

Closes #2649, whose lower-level half includinguse_prepared_state and use_transitive_state is already shipped

This PR implements the higher-level half of #2649: a yew-link crate that unifies SSR, hydration, and client-side data fetching behind a single hook.

The mentioned lower-level hooks already carry server-computed state to the client during hydration. But after that initial page load, client-side navigation requires a completely separate fetch path. This means every data-dependent component needs two code paths stitched together manually. yew-link closes this gap.

Implimented new crates proposed in the pr: yew-link and yew-link-macro

Overhauled ssr_router example, rewired to use yew-link instead of generating content inline. Demonstrates #[linked_state], LinkProvider, use_linked_state, Resolver::register_linked, and the axum handler, with full SSR-to-hydration state transfer and client-side nav fetching.

See the new website changes to understand the usage pattern

Comparison with Bounce's Query API

@futursolo's Bounce, whose Query API and use_prepared_query hook do overlapping but not identical work

yew-link does better on code isolation as its #[linked_state] strips resolve() from WASM and Query::query() body is always compiled into WASM.

yew-link also provides better utility by its built-in linked_state_handler for axum.

After #4013 merges

#4013 replaces the hand-maintained feature-soundness scripts with cargo-hack --feature-powerset. Once it lands:

  • Add yew-link to the cargo hack clippy -p ... list in .github/workflows/clippy.yml and packages/yew/Makefile.toml so its feature combinations (ssr, hydration, axum) are covered automatically.
  • Add yew-link,yew-link-macro to --exclude-features if any of their features shouldn't participate in the powerset (will check).

Remaining TODOs (future PRs)

  • Cache invalidation / refresh, expose a .refresh() method or TTL-based expiry.
  • Non-suspending variant, a use_linked_state_value that returns Loading | Ok | Err instead of suspending.
  • Mutations, write-side counterpart to use_linked_state.
  • Deduplication, multiple components requesting the same (T, input) concurrently should share a single in-flight request.
  • Tests, unit tests for the hook (SSR + hydration + CSR paths) and integration tests for the axum handler.

Basically everything else Bounce does correctly

I'm not sure how cargo release in our .github/workflows/publish.yml handles the two added new crates, but that's a matter for the future when when publish yew-link with yew 0.23

Checklist

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

I have to think about tests.
I manually tested the uphauled ssr_example and paid attention to the network requests. The claims hold well: directly visiting a post by its url receives a server-rendered page. In-app navigation goes through fetch.

E2e testing directly on the example might be a good idea, which requires resolving #196 first.

github-actions[bot]
github-actions bot previously approved these changes Mar 1, 2026
@github-actions
Copy link

github-actions bot commented Mar 1, 2026

Visit the preview URL for this PR (updated for commit 5c337a4):

https://yew-rs--pr4027-yew-link-sylkdib6.web.app

(expires Sun, 08 Mar 2026 05:38:26 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

github-actions[bot]
github-actions bot previously approved these changes Mar 1, 2026
@github-actions
Copy link

github-actions bot commented Mar 1, 2026

Benchmark - SSR

Yew Master

Details
Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 310.749 313.064 311.293 0.672
Hello World 10 467.443 491.807 474.039 9.395
Function Router 10 31374.284 31806.908 31603.390 158.553
Concurrent Task 10 1006.226 1009.943 1007.428 1.018
Many Providers 10 1066.089 1127.129 1098.929 16.895

Pull Request

Details
Benchmark Round Min (ms) Max (ms) Mean (ms) Standard Deviation
Baseline 10 310.847 317.339 311.678 1.996
Hello World 10 468.149 473.579 471.135 1.858
Function Router 10 31353.471 31849.147 31669.864 156.539
Concurrent Task 10 1004.796 1007.833 1006.725 0.906
Many Providers 10 1097.205 1128.673 1107.454 8.513
@github-actions
Copy link

github-actions bot commented Mar 1, 2026

Size Comparison

Details
examples master (KB) pull request (KB) diff (KB) diff (%)
async_clock 100.196 100.196 0 0.000%
boids 168.080 168.080 0 0.000%
communication_child_to_parent 93.471 93.471 0 0.000%
communication_grandchild_with_grandparent 105.247 105.247 0 0.000%
communication_grandparent_to_grandchild 101.604 101.604 0 0.000%
communication_parent_to_child 90.897 90.897 0 0.000%
contexts 105.151 105.151 0 0.000%
counter 86.281 86.281 0 0.000%
counter_functional 88.274 88.274 0 0.000%
dyn_create_destroy_apps 90.319 90.319 0 0.000%
file_upload 99.342 99.342 0 0.000%
function_delayed_input 94.374 94.374 0 0.000%
function_memory_game 172.940 172.940 0 0.000%
function_router 405.773 405.773 0 0.000%
function_todomvc 164.160 164.160 0 0.000%
futures 235.158 235.158 0 0.000%
game_of_life 104.717 104.717 0 0.000%
immutable 255.871 255.871 0 0.000%
inner_html 80.802 80.802 0 0.000%
js_callback 109.380 109.380 0 0.000%
keyed_list 179.727 179.727 0 0.000%
mount_point 84.146 84.146 0 0.000%
nested_list 113.059 113.059 0 0.000%
node_refs 91.524 91.524 0 0.000%
password_strength 1729.151 1729.151 0 0.000%
portals 93.036 93.036 0 0.000%
router 376.334 376.334 0 0.000%
suspense 113.455 113.455 0 0.000%
timer 88.633 88.633 0 0.000%
timer_functional 98.880 98.880 0 0.000%
todomvc 142.087 142.087 0 0.000%
two_apps 86.146 86.146 0 0.000%
web_worker_fib 136.238 136.238 0 0.000%
web_worker_prime 187.468 187.468 0 0.000%
webgl 83.225 83.225 0 0.000%

✅ None of the examples has changed their size significantly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-yew-link Area: The yew-link crate

1 participant