You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/blog/tanstack-router-signal-graph.md
+15-5Lines changed: 15 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -101,10 +101,10 @@ useStore(matchStore, (match) => /* select from one match */)
101
101
102
102
> [!NOTE]
103
103
> `getMatchStoreByRouteId` creates a derived signal on demand, and stores it
104
-
> in a Least-Recently-Used cache so it can be reused by other subscribers
104
+
> in a Least-Recently-Used cache[^lru-cache] so it can be reused by other subscribers
105
105
> without leaking memory.
106
106
107
-
The store-update-count graphs below show how many times subscriptions are invoked during various routing scenarios, before (curve is the entire history) and after (last point is this refactor).
107
+
The store-update-count graphs below show how many times subscriptions are invoked during various routing scenarios, before (curve is the entire history) and after (last point is this refactor).[^store-update-tests]
108
108
109
109
<!-- ::start:tabs -->
110
110
@@ -172,14 +172,14 @@ export type StoreConfig = {
172
172
This keeps one router core while letting each adapter plug in the store model it wants.
173
173
174
174
> [!NOTE]
175
-
> Solid's derived stores are backed by native memos, and the adapter uses a `FinalizationRegistry`
175
+
> Solid's derived stores are backed by native memos, and the adapter uses a `FinalizationRegistry`[^finalization-registry]
176
176
> to dispose detached roots when those stores are garbage-collected.
177
177
178
178
## Observable Result: Less Work During Navigation
179
179
180
180
No new public API is required here. `useMatch`, `useLocation`, and `<Link>` keep the same surface. The difference is that navigation and preload flows now wake up fewer subscriptions.
181
181
182
-
Our benchmarks isolate client-side navigation cost on a synthetic rerender-heavy page.
182
+
Our benchmarks isolate client-side navigation cost on a synthetic rerender-heavy page.[^client-nav-bench]
183
183
184
184
- React: `7ms -> 4.5ms`
185
185
- Solid: `12ms -> 8ms`
@@ -216,7 +216,7 @@ This graph shows the duration of 10 navigations on <code>main</code> (grey) and
216
216
217
217
<!-- ::end:tabs -->
218
218
219
-
There is also a bundle-size tradeoff. In our synthetic bundle-size benchmarks, measuring gzipped sizes:
219
+
There is also a bundle-size tradeoff. In our synthetic bundle-size benchmarks, measuring gzipped sizes:[^bundle-size-bench]
220
220
221
221
- ↗ React increased by `~1KiB`
222
222
- ↗ Vue increased by `~1KiB`
@@ -266,3 +266,13 @@ Routing is a graph. Now the reactivity is one too.
266
266
[^alien-migration]: [TanStack Store PR #265](https://github.com/TanStack/store/pull/265)
267
267
268
268
[^alien-bench]: [js-reactivity-benchmark](https://github.com/transitive-bullshit/js-reactivity-benchmark) last updated january 2025
269
+
270
+
[^store-update-tests]: Methodology and exact scenario assertions live in the adapter test files for [React](https://github.com/TanStack/router/blob/refactor-signals/packages/react-router/tests/store-updates-during-navigation.test.tsx), [Solid](https://github.com/TanStack/router/blob/refactor-signals/packages/solid-router/tests/store-updates-during-navigation.test.tsx), and [Vue](https://github.com/TanStack/router/blob/refactor-signals/packages/vue-router/tests/store-updates-during-navigation.test.tsx).
271
+
272
+
[^lru-cache]: For a great JavaScript-oriented explanation of how LRU caches work, see [Implementing an efficient LRU cache in JavaScript](https://yomguithereal.github.io/posts/lru-cache/).
273
+
274
+
[^finalization-registry]: A [FinalizationRegistry](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry) allows us to hook into the Garbage Collector to execute arbitrary cleanup functions when an object gets collected.
275
+
276
+
[^client-nav-bench]: These numbers come from the [`benchmarks/client-nav`](https://github.com/TanStack/router/tree/main/benchmarks/client-nav) CodSpeed suite, which runs a 10-navigation loop against a synthetic page that intentionally mounts many `useParams`, `useSearch`, and `Link` subscribers to amplify propagation costs. See [CodSpeed](https://codspeed.io/TanStack/router), and the [React app fixture](https://github.com/TanStack/router/blob/main/benchmarks/client-nav/react/app.tsx).
277
+
278
+
[^bundle-size-bench]: These numbers come from the deterministic fixtures in [`benchmarks/bundle-size`](https://github.com/TanStack/router/tree/main/benchmarks/bundle-size), measured from the initial-load JS graph and tracked primarily as gzip deltas. See the [README](https://github.com/TanStack/router/blob/main/benchmarks/bundle-size/README.md).
0 commit comments