Skip to content

fix(router): warm prefetched route navigations - #2100

Merged
dai-shi merged 11 commits into
wakujs:mainfrom
jxom:jxom/fix-router-prefetch-warmth
Jun 3, 2026
Merged

dai-shi merged 11 commits into
wakujs:mainfrom
jxom:jxom/fix-router-prefetch-warmth

Conversation

@jxom

@jxom jxom commented May 25, 2026

Copy link
Copy Markdown
Contributor

Fixes #2099.

Router prefetch now maps route module ids against the shared prefetch id table, which keeps production preload callbacks aligned with the chunks for the requested route.

RSC prefetch now starts decoding the prefetched response and stores the resulting elements with the prefetched entry. Matching navigations reuse those elements instead of creating them for the first time on click.

@vercel

vercel Bot commented May 25, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
waku Ignored Ignored Preview Jun 3, 2026 2:33am

Request Review

@codesandbox-ci

codesandbox-ci Bot commented May 25, 2026 •

Copy link
Copy Markdown

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@pkg-pr-new

pkg-pr-new Bot commented May 25, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/waku@2100

commit: d96dd8a

@jxom
jxom marked this pull request as ready for review May 25, 2026 01:17

@dai-shi dai-shi 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.

Thanks for working on it!! Do you think you can add some tests to cover the fix? I would like to refactor based on it.

Comment thread packages/waku/src/lib/utils/prefetch.ts Outdated
export type INTERNAL_PrefetchedEntry = {
[KEY_RSC_PATH]: string;
[KEY_RESPONSE]: Promise<Response>;
[KEY_ELEMENTS]?: unknown;

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.

Now, it feels like we should drop KEY_RESPONSE and make KEY_ELEEMENTS required. This will require separating initial server prefetch (bad naming) structure from client prefetch structure. I'll try that in a follow-up PR.

Comment thread packages/waku/src/minimal/client.tsx Outdated
});
if (prefetchOnly) {
const elements = createElements();
Promise.resolve(elements).catch(() => {});

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.

Do we need this?

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.

// Observe failed prefetches until a matching navigation consumes them.

Hmmm, I'm not sure how it helps.

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.

Is it to hide unhandled promise error? Makes sense, but the comment can be different?

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.

I think the error is handled if the prefetched entry is actually "used". So, this workaround is only for the case when the prefetched entry is never used. Is it correct?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah, I think if the prefetched entry is consumed by navigation, unstable_fetchRsc reuses the decoded elements promise and the rejection is handled through that path. This catch is only for abandoned prefetches that are never consumed, where nothing else observes the promise. can update the comment.

Comment on lines +404 to +405
Object.entries(path2moduleIds).forEach(([path, pathIds]) => {
path2idxs[path] = pathIds.map((id) => ids.indexOf(id));

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.

Oh my... This is such a fundamental bug... Thanks for the catch.

@dai-shi

dai-shi commented May 25, 2026

Copy link
Copy Markdown
Member

@jxom #2099 (comment)

@jxom

jxom commented May 25, 2026

Copy link
Copy Markdown
Contributor Author

Closing in favor of the focused replacement PR: #2102. It keeps only the router prefetch module id mapping fix.

@jxom jxom closed this May 25, 2026
@dai-shi dai-shi reopened this May 26, 2026
@dai-shi

dai-shi commented May 26, 2026

Copy link
Copy Markdown
Member

#2102 is merged, so reopened.

@dai-shi dai-shi 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.

Now, I'm comfortable with this.
(I think Unstable_FetchRscStore should be revisited entirely in the near future.)

@dai-shi
dai-shi merged commit 3259e01 into wakujs:main Jun 3, 2026
28 checks passed
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.

Router prefetch does not fully warm route navigations

2 participants