How to Show Loader on Page Changes in Next.js

To read more articles like this, visit my blog

We all love Next.js. It feels like a supercharged version of React. The nice thing about Next.js is it can render both on the client side and server side.

The idea of server-side rendering is we pre-generate all our pages with the appropriate amount of HTML and CSS and deliver the whole page when requested.

But that comes with a cost!

The problem

The problem is when the user clicks on any route to go to another page, the fetching request needs to be finished first to be shown to the user.

And the user generally doesn’t have any clue what’s going on because there is no visual clue on the screen.

To solve this problem, we can introduce a nice trick to indicate when it’s loading to the user. And we have two ways to do that.

First Solution

There is a nice library named nextjs-progressbar just to serve this purpose. You can see the result of using this library here

To use this library, first install it

yarn add nextjs-progressbar

Then go inside your _app.tsx file and import it

import NextNprogress from 'nextjs-progressbar';

Then just render the component along with your <Component /> inside the _app.tsx . The final result will look something like the following.

import { AppProps } from 'next/app';
import NextNprogress from 'nextjs-progressbar';

function CustomApp({ Component, pageProps }: AppProps) {

    return (
        <main>
            <NextNprogress />
            <Component {...pageProps} />
        <main/>
    );
}

export default CustomApp;

And now you will have a nice loader when you are changing routes.

Problem with the First Solution

This package is built using another nice package that is hugely popular. That is called nprogress .

It just takes away all the complexity from you. But there is a catch. The bundle size of the nprogress is much, much smaller than nextjs-progressbar .

Comparison between 2 libraries

So from the comparison, we see that we can save around 14kb if we go with the default library named nprogress. But it will take a little more effort to get it to work.

Better Solution with Nprogress

Let's install the dependency first

yarn add nprogress

Then go inside your _app.tsx file and import Nprogress

    import NProgress from 'nprogress';
    import 'nprogress/nprogress.css';

    import Router from 'next/router';

Now we are importing the CSS file also. If you want to customize the CSS, you can do that too. Just include the CSS file inside the project itself. It's very minimal. Here is the link to that file

We will also need to import Router because we have to detect the route changes.

Now we will bind the Nprogress with our Router like the following.

Router.events.on('routeChangeStart', (url) => {
    console.log(`Loading: ${url}`);
    NProgress.start();
});
Router.events.on('routeChangeComplete', () => NProgress.done());
Router.events.on('routeChangeError', () => NProgress.done());

The events are pretty self-explanatory. we are starting Nprogress when the route change starts. And turning it off when the route change is finished.

Now our _app.tsx should look something like the following

import { AppProps } from 'next/app';

import NProgress from 'nprogress';
import 'nprogress/nprogress.css';

import Router from 'next/router';

Router.events.on('routeChangeStart', (url) => {
    console.log(`Loading: ${url}`);
    NProgress.start();
});

Router.events.on('routeChangeComplete', () => NProgress.done());
Router.events.on('routeChangeError', () => NProgress.done());


function CustomApp({ Component, pageProps }: AppProps) {
    return <Component {...pageProps} />;
}

export default CustomApp;

This will have the same effect just like before. But this will cause a much less bundle size.

Final Thoughts

There are multiple ways to make your application better. You should always look for ways to improve your application's performance and user experience.

Have something to say? Get in touch with me via LinkedIn or Personal Website