Replies: 17 comments 25 replies
-
In development prefetching is disabled.
This comes down to just this code:
|
Beta Was this translation helpful? Give feedback.
-
What I've done is create a Babel plugin local to my project which adds 1 - Create a file at eg /**
* Based on the docs at https://nextjs.org/docs/api-reference/next/link, the
* only way to disable prefetching is to make sure every <Link /> has <Link
* prefetch={false} />
*
* We don't want to create a wrapper Component or go around changing every
* single <Link />, so we use this Babel Plugin to add them in at build-time.
*/
module.exports = function (babel) {
const { types: t } = babel
return {
name: 'disable-link-prefetching',
visitor: {
JSXOpeningElement(path) {
if (path.node.name.name === 'Link') {
path.node.attributes.push(
t.jSXAttribute(
t.jSXIdentifier('prefetch'),
t.JSXExpressionContainer(t.booleanLiteral(false)),
),
)
}
},
},
}
} 2 - Add/modify {
"presets": ["next/babel"],
"plugins": ["./babel/disable-nextjs-link-prefetching"]
} |
Beta Was this translation helpful? Give feedback.
-
A workaround that I use for disabling hover prefetch as well is essentially this: import React from "react";
import { Router, withRouter } from "next/router";
type Props = {
href: string;
children: React.ReactNode;
router: Router;
};
class LinkNoPrefetch extends React.PureComponent<Props> {
onClick = async (event: React.MouseEvent) => {
const { router, href } = this.props;
event.preventDefault();
await router.push(href);
}
render() {
const { href, children } = this.props;
return (
<a href={href} onClick={this.onClick}>
{children}
</a>
);
}
}
export default withRouter(LinkNoPrefetch); |
Beta Was this translation helpful? Give feedback.
-
PROBLEM: Unreliable page view logs The idea is that admins could read from the logs which pages are viewed and by whom. If the user only hovers over the link it now creates a request. This can give a false information about what pages the user really visited. |
Beta Was this translation helpful? Give feedback.
-
After trying a few workaround, I decided to patch nextjs router directly
|
Beta Was this translation helpful? Give feedback.
-
The prefetching should come with warnings and the next/link component should not be forced on you. The only reason I used it was that during build time, It would not allow me to proceed until I changed all internal tags to a link component. This absolutely destroyed my serverless functions limit in 8 days and forced me to take down my projects due to the crazy costs that would have incurred. Even after disabling prefetch it still fetches every single link the person's mouse scrolls over while navigating down the page. So much extra tax on the backend slows the site down and costs you a bunch of extra money for nothing. *Edited to be a bit less obscene. I may have jumped the gun on this one. I still think they should warn newcomers and put a warning for sites with lots of links on the documentation. But they obviously know what they are doing when it comes to optimizing. It just leaves a pretty sour taste in the mouths of newcomers when they get stung with nasty bills. Prefetch behavior + WP jam stack is a total fail on ecom sites with lots of links. Especially since the behavior is different in dev vs production. It's a costly lesson to learn. |
Beta Was this translation helpful? Give feedback.
-
There's another option that the framework could provide that could provide a balance to this issue. Rather than prefetch all the things, why not provide the developer with a little control over the way things are bundled. In the pre-framework isomorphic days, it used to be simple to control code splitting. Use dynamic import when you want it, and don't when you don't. Per page resources is safe and a good starting point, but it is a valid performance trade off decision to consider an initial bundle with a few common routes. In my experience, that's a better overall UX for the client and doesn't require hitting the server needlessly. Of course that goes against Google's holy grail of of small initial payload over everything else no matter what. So you'd have to go easy with this power to please the SEO gods (and yeah of course mobile), but in my experience adding 25k or so to gain a handful of "pre" prefetched routes doesn't hurt "nearly" as bad as adding 2mb+ of ad and tracking libraries. |
Beta Was this translation helpful? Give feedback.
-
So the new Link prefetch behavior seems to be broken? If you set |
Beta Was this translation helpful? Give feedback.
-
Just write your own link tag, it's easy:
Note that this is an example and probably has one or two mistakes. |
Beta Was this translation helpful? Give feedback.
-
From what I can tell, v13.2.4 (app directory) doesn't prefetch on hover.
|
Beta Was this translation helpful? Give feedback.
-
I can't speak for why they didn't in the past, but as someone mentioned above it's now possible. What I'd do is make a little wrapper over Link and change the default prefetch to false. Something like: import NextLink, { type LinkProps } from 'next/link';
type CustLink = LinkProps & { children: React.ReactNode };
export function Link({ href, prefetch = false, children, ...rest }: CustLink) {
return (
<NextLink href={href} prefetch={prefetch} {...rest}>
{children}
</NextLink>
);
} |
Beta Was this translation helpful? Give feedback.
-
@unleashit Thanks for the code! I was getting a Type error when adding a
// components/Link.tsx
import { forwardRef, type AnchorHTMLAttributes, type ReactNode } from "react"
import NextLink, { type LinkProps as NextLinkProps } from "next/link"
type LinkProps = NextLinkProps &
Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof NextLinkProps> & {
children?: ReactNode
}
export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
function LinkWithRef(
{
// Turn next/link prefetching off by default.
// @see https://github.com/vercel/next.js/discussions/24009
prefetch = false,
...rest
},
ref
) {
return <NextLink prefetch={prefetch} {...rest} ref={ref} />
}
) |
Beta Was this translation helpful? Give feedback.
-
Took me two hours to realise why my users are automatically logged off upon logging in to the admin panel; because one of the links was "Sign off" without damn prefetch. Now, when they hover over on "sign off" without the intention of being logged off, it will still happen unless I use . |
Beta Was this translation helpful? Give feedback.
-
I'm using v14.1.0 pages router with The easiest way to disable prefetching is to patch nextjs source code, forget about the workarounds mentioned above, just patch it! patches/next+14.1.0.patch
|
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
Here is how I fix it simply. import Link from 'next/link';
import type { LinkProps } from 'next/link';
const OriginalLink = Link;
Object.defineProperty(Link, 'default', {
configurable: true,
writable: true,
value: (props: LinkProps) => {
return <OriginalLink {...props} prefetch={props.prefetch ?? false} />;
},
}); |
Beta Was this translation helpful? Give feedback.
-
Describe the feature you'd like to request
Please allow
<Link>
prefetching to be globally disabled, or enabled one a one-to-one basis.In development mode prefetching raises the noise to signal ratio, and makes it difficult to get a sense of the page footprint.
In production mode prefetching is not always desirable and Next should not try to outsmart the developer.
Globally disabling prefetching currently involves implementing your own Link element which is cumbersome, or making sure that every in your app has prefetch set to false.
Describe the solution you'd like
One solution may be to allow prefetching to be globally disabled by setting an entry in
next.config.js
. Setting such entry should set the defaultprefetching
strategy of<Links>
when a value is not set.Possible values may be:
An alternative solution may be to let the developer writing a JS function to determine if the fetch should happen or not.
Describe alternatives you've considered
I found none.
Beta Was this translation helpful? Give feedback.
All reactions