How to Show Loader on Page Changes in Next.js
Tags: nextjs, javascript, react, programming
Published: 2023-11-03 16:01:27

To read more articles like this, [visit my blog](https://www.mdfaisal.com/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 must be finished first to be shown to the user.

And the user generally doesn’t know 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](https://www.npmjs.com/package/nextjs-progressbar) just to serve this purpose. You can see the result of using this library [here](https://demo-nextjs-progressbar.vercel.app/)

To use this library, first install it

```js
yarn add nextjs-progressbar
```

Then go inside your `_app.tsx` file and import it

```js
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.

```js
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](https://www.npmjs.com/package/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` .

![](https://cdn-images-1.medium.com/max/2560/1*syfTmOJVYESP9Y8-Yt8FgQ.png)

![Comparison between 2 libraries](https://cdn-images-1.medium.com/max/2560/1*AAFvCA7PtMchmZwarlWlzQ.png)

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

```js
yarn add nprogress
```

Then go inside your `_app.tsx` file and import `Nprogress`

```js
    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](https://github.com/rstacruz/nprogress/blob/master/nprogress.css) 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.

```js
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

```js
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](https://www.linkedin.com/in/56faisal/) or [Personal Website](https://www.mdfaisal.com/)**