Three ways to achieve instant navigation
Links in next.js feels laggy if the user has slow internet / server response with delays / serverless function hits a cold start. It ruins UX. And most likely, users will click fewer links because of those delays. If every link always opened instantly, users would be more active on the website. Fast navigation improves UX, user engagement, and positively impacts SEO. Let's look at three ways to achieve instant navigation.
Prefetch
Prefetching preloads the route and its data in the background before the user visits it. When the next/link component is used, it's enabled by default. It's very effective and easy to use. Prefetch, however, has some drawbacks.
- Prefetch wastes a lot of user resources, like battery life and internet traffic
- The server receives numerous redundant requests. For example, a user can prefetch a whole list of products/articles and never open any of them. This increases the load on the server.
- If the user clicks a link before prefetch is complete, it will open with a delay.
Usually, prefetch works in two modes:
- Prefetch all visible links. If a link is visible in the user's viewport, it will be prefetched. If your website has a lot of internal links, I don't recommend using it.
- Prefetch only hovered links. Users who can hover links typically possess unlimited internet access and a robust battery, making them less susceptible to unnecessary prefetching. Furthermore, hovering a link increases the likelihood of its click, which reduces the number of unnecessary requests sent. However, mobile users are unable to hover, which means they will open links with delay.
Prerender links with A.I
Here's a new API, currently available only in chromium browsers. Think of it as a hint for the browser, indicating which links can be prerendered. If the browser decides to prerender one of them, that link will be opened in an invisible tab and rendered. The user will instantly see the prerendered version after clicking that link.
<script type="speculationrules">
{
"prerender": [
{
"urls": ["next.html", "next2.html"]
}
]
}
</script>
<script type="speculationrules">
{
"prerender": [{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": {"href_matches": "/wp-admin"}},
{ "not": {"href_matches": "/*\\?*(^|&)add-to-cart=*"}},
{ "not": {"selector_matches": ".do-not-prerender"}},
{ "not": {"selector_matches": "[rel~=nofollow]"}}
]
}
}]
}
</script>
It has the same drawbacks as prefetch and can waste even more user resources because render operations are expensive. A.I. can reduce the number of prerendered pages that never opened. But from time to time, useless prerenders will happen anyway.
Optimistic navigation
Instead of wasting user resources on prefetching or prerendering, this optimization creates the illusion of instant navigation. When navigation happens, a page immediately displays with demo data while the main data is loading. Ideally, that demo data should have enough content to display the first screen of the page. Covering the first screen with demo data gives the impression of instant navigation.
// pages/index.tsx
export const getServerSideProps = () => {
const articles = [{
thumbnail: '...',
title: '...',
description: '...',
}];
return {
props: articles
};
}
// pages/blog/[slug]/index.tsx
export const getServerSideProps = () => {
const article = {
thumbnail: '...',
title: '...',
description: '...',
content: '...',
};
return {
props: article
};
}
The idea behind optimistic navigation is very simple, but it's challenging to implement in modern meta-frameworks. I'll explain how to implement optimistic navigation in the next article. You can see optimistic navigation in action on that website. Turn off optimistic navigation toggler in the header to see how next.js works by default.
Summary
Instantaneous navigation is a challenging task, pays off with satisfied users. Here's 3 way to achieve it. Advantages and disadvantages of each way displayed bellow.
| Advantages | Optimistic navigation | Prerender | Prefetch |
|----------------------------|-----------------------|-----------|----------|
| No waste of user resources | + | - | - |
| No extra server load | + | +/- | - |
| Permanently instant | + | - | - |
| Easy to implement | - | +/- | + |
As you can see from the table above, optimistc navigation have some advantages over prefetchin and prerendering. With well-tuned optimistic navigation, the server can send responses in 600-800 ms, and the user will not notice network lag at all. This gives a good headroom for the load balancer. Effect of that optimisation will be especially noticable on big applications with a lot of links, and a lot of clients.