-
Notifications
You must be signed in to change notification settings - Fork 26k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Future <Link> navigation is broken if prefetching that route takes longer than 3.8 sec #28797
Comments
This fixes it for us, and what we're now running in production: jayphelps@8daaa0a - generator().then((value) => (resolver(value), value))
+ generator()
+ .then((value) => (resolver(value), value))
+ .catch((e) => {
+ map.delete(key)
+ throw e
+ }) Though it's probably a good idea to catch any synchronous errors when calling |
Edited original post to include a repo to reproduce the issue easily; I patched next-server.js in the node_modules (included) so that it always has 5 seconds of latency for the /about route chunk. https://github.com/jayphelps/next-issue-28797 |
This applies the fix from the awesome investigation done in #28797 by @jayphelps and adds a test to ensure this is working as expected. It seems that the `route-loader` has a race condition while prefetching and if a script is executed before we have created a current "future" entry to resolve the entry stays in a pending state causing routes to hang so this handles the condition by ensuring pending/errored entries do not stay around. ## Bug - [x] Related issues linked using `fixes #number` - [x] Integration tests added - [x] Errors have helpful link attached, see `contributing.md` Fixes: #28797 Fixes: #27783
This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
What version of Next.js are you using?
11.1.2/Canary
What version of Node.js are you using?
Any
What browser are you using?
Any
What operating system are you using?
Any
How are you deploying your application?
Any
Describe the Bug
The internal utility
withFuture()
sets internal state in the routes Map containing a Promise. When loading or prefetching, the internalloadRoute()
uses theresolvePromiseWithTimeout ()
, which will reject after the given 3.8 second timeout.If a route is navigated to for the first time without being prefetched, and the 3.8 timeout is triggered due to slow server/connection, an exception is thrown and ultimately the page will do a full navigation. However, if an attempt to prefetch the route is made by Next and it takes longer than 3.8 seconds, that exception is caught and swallowed in production mode. Because
withFuture()
does not listen for any rejections from the promise returned fromgenerator()
(or, unrelated, if generator() synchronously threw) the state stored inroutes
(passed intowithFuture
as the second argument ,map
) is not cleaned up and the "future" promise stored in there will never be resolved nor rejected.When induced, the symptom from the user is that clicking a
<Link>
does nothing visually, and no error is logged.Expected Behavior
Preloading
<Link>
s that take longer than the timeout do not prevent future navigation to that route.To Reproduce
To reproduce, clone/build/start this repo, but do NOT npm install because I've patched next to induce 5 second latency to the /about JS chunk only to make it easily reproducible: https://github.com/jayphelps/next-issue-28797
Alternatively, the general instructions for making your own:
<Link href="/something">
to another page (without settingprefetch={false}
)./_next/static/chunks/pages/file.js
for that particular page; it's much harder to reproduce if you induce general latency on everything, but consistently reproducible if only that one file.<Link>
.<Link>
.To confirm root cause, add a breakpoint to the prefetch error swallowing line, reproduce (seeing debugger pause on that breakpoint), then inspect internal
routes
map to see the hung promise stuck in 'pending' state forever.If things are unclear, I'm happy to jump on Zoom, etc.
As always, apologies if I'm some how wrong and waste anyone's time 😅 I tried to be thorough. I would PR, but it’s unclear if the right approach is a more extreme refactor or just simply tweaking withFuture to listen for errors and cleanup—that might have consequences I’m unaware of because it’s used in several places.
The text was updated successfully, but these errors were encountered: