[RSC HMR] Fix a flurry of refetches when a editing component imported from many routes#96102
Merged
Conversation
Contributor
Tests PassedCommit: 674229b |
Contributor
Stats from current PR🟢 2 improvements
📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📎 Tarball URLCommit: 674229b |
gaearon
force-pushed
the
gaearon-hmr-coalesce
branch
5 times, most recently
from
July 24, 2026 02:23
5899a52 to
8ca4780
Compare
Each route endpoint that an edit affects emits its own serverComponentChanges message. A client refetches its page once per received message, so with six routes importing the edited component, one edit makes every connected client refetch six times. The tests pin the expected behavior: exactly one refetch per edit, none for an edit whose compilation errored. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
serverComponentChanges tells a client to refetch its page, but it was sent once per affected route endpoint. An edit to a file shared by many built routes delivered one copy per route to every client, and each copy triggered a full RSC refetch of the same page. Editing the root layout of vercel-docs with 13 routes built delivered 23 messages per client, i.e. 23 identical refetches per open tab per save, growing as more routes were built. The message is about the update, not about a route: route endpoint change subscriptions now only note that server components changed, and the update's end flush announces it once. A change event that arrives outside an update is announced immediately. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gaearon
force-pushed
the
gaearon-hmr-coalesce
branch
from
July 24, 2026 02:32
8ca4780 to
674229b
Compare
gaearon
marked this pull request as ready for review
July 24, 2026 02:37
wbinnssmith
approved these changes
Jul 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a flurry of requests when doing server HMR.
To reproduce the issue, create a server component imported from multiple routes:
/aimports that component/bimports that component/cimports that componentThen edit that server component.
Expected: one request in terminal per open tab.
Actual: a flurry of requests.
There's two separate causes for the flurry of requests:
debouncefor these messages is broken (it always fires instead of delaying) due to a wrong condition inside it. So if we tried coalescing messages by key, we'd still see multiple requests per tab.debouncebut that's more risky because I don't know if either existing caller could rely on the bug. Luckily, for the fix below this doesn't matter.Anyway, to get the desired behavior (one refresh per page), we switch to expressing server component changes as a final message that gets sent at the end of the update using a dirty flag. Then we don't need to worry about how they get deduped or how many of them gets received.
There are probably other ways to factor this but this one seemed fine to me.
Before
A flurry of requests.
bugggg.mov
After
One request per open tab.
afterrr.mov