12

I have a website built in React Js and the same one on Next Js as well.

The problem which I am facing right now is, the router seems very slow in the nextJs compare to react-router-dom, It's taking almost 2-3 seconds to change the route.

Here are the URLs where you can feel the difference between the performance by moving around different pages.

https://cutt.ly/mhbPkOE (React Router Dom) vs https://cutt.ly/BhbPvHv (NextJs)

I had read some comments on Github where few experts are saying that It will resolve in production. but It looks same in production too.

Please have a look at the following code

_app.jsx

// import App from 'next/app'
import React from "react"
import Router from 'next/router';

import "../static/sass/application.scss";

import "bootstrap/dist/css/bootstrap.min.css";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import 'semantic-ui-css/semantic.min.css'
import { wrapper } from "../../redux/utils/store"

import App from 'next/app';
// A simple component that we created
import {LoaderOverlay} from '../components/Reusable'
class MyApp extends App {
    constructor(props){
        super(props)
        this.state = {
            isLoading: false,
        }
        Router.onRouteChangeStart = (url) => {
            // Some page has started loading
            this.setState({
                isLoading: true,
            }) // set state to pass to loader prop
        };
    
        Router.onRouteChangeComplete = (url) => {
            // Some page has finished loading
            this.setState({
                isLoading: false,
            }) // set state to pass to loader prop
        };
    
        Router.onRouteChangeError = (err, url) => {
            this.setState({isLoading: false,})
        }; 
    };
    render() {
        const {Component, pageProps} = this.props
        return (
            <div>
                {this.state.isLoading ? (
                    <LoaderOverlay/>
                ) : (
                    <Component {...pageProps} />
                )}
            </div>
        )
    }
}
export default wrapper.withRedux(MyApp);

_document.jsx

import Document, { Html, Head, Main, NextScript } from 'next/document'

class MyDocument extends Document {
    static async getInitialProps(ctx) {
        const originalRenderPage = ctx.renderPage

        ctx.renderPage = () =>
            originalRenderPage({
            // useful for wrapping the whole react tree
            enhanceApp: (App) => App,
            // useful for wrapping in a per-page basis
            enhanceComponent: (Component) => Component,
            })

        // Run the parent `getInitialProps`, it now includes the custom `renderPage`
        const initialProps = await Document.getInitialProps(ctx)

        return initialProps
    }

    render() {
        return (
            <Html lang="en">
                <Head>
                <link async rel="stylesheet" href="//cdn.jsdelivr.net/npm/semantic-ui@2.4.1/dist/semantic.min.css"/>
                </Head>
                <body>
                    <div className={'main-wrapper'}>
                        <Main />
                    </div>
                    <NextScript />
                </body>
            </Html>
        )
    }
}

export default MyDocument
juliomalves
  • 42,130
  • 20
  • 150
  • 146
Muhammad Owais
  • 980
  • 3
  • 17
  • 37
  • well that is because in next.js the pages are server-rendered while on SPA react it isn't you can render your pages as static pages on next.js depends on your needs everything has its pros and cons maybe it is better to build your app as React SPA if you don't need SEO optimization. – Mostafa Hesham Dec 04 '20 at 16:22
  • well, I already have this app in React JS, but obviously I need SEO optimized as well that's why I choose Next Js to make my app SEO friendly. I was hoping It won't affect performance at least in the router. – Muhammad Owais Dec 04 '20 at 16:27
  • Same problem in 2023. I have a very minimalistic app, some routes don't need any new data from the server (all the data is already on the page, I just have cards that when clicked are opened in a modal and show the data in a bit different format). I'm using shadow routing (when the actual URL that the browser sees is different from what the router sees). I have the `shallow` prop on all the `Link`s. Somehow, still, in production, my cards are taking anywhere from 300ms to 2s to open in a modal. If I use React useState to track the opened card instead of the router, the opening takes 50ms – Art Ginzburg May 24 '23 at 08:32

5 Answers5

8

Development mode (next dev) is much slower because the routes aren't pre-built.

All delay related to routing assuming you don't have any server side blocking data requirements via getInitialProps, getServerSideProps, should not be present when running production mode with next build followed by next start.

agusterodin
  • 417
  • 1
  • 5
  • 17
  • This is helpful. I initially had a `server.js` file created to serve my app in Azure (_which meant I cannot use `next start`_) and it was very slow (**around 11s**). But based on [this answer](https://stackoverflow.com/a/69779272/6908282), I used `PM2` to serve my application from Azure App service and now the app in production is quick (**around 250ms**) – Gangula Dec 22 '21 at 09:25
0

Not sure if you have found a fix for this yet, but I came across this article about "shallow routing". I can't see much improvement in my application when using it, but maybe it will help someone else:

https://nextjs.org/docs/routing/shallow-routing

phunder
  • 1,607
  • 3
  • 17
  • 33
0

I'm unable to access your cutt.ly examples, but I've encountered a similar issue when using router.push(/dashboard/some_path). The issue arises because every time you use router.push, it triggers getInitialProps for the page from scratch. This can be quite expensive in terms of performance, especially if you're doing heavy calculations in your React code. To mitigate this, you might want to consider expensive operations as much as possible. In my case, I replaced the following code:

import { useRouter } from "next/router";
const router = useRouter();
const mypath = `/dashboard/some_path`;
router.push(mypath);

With:

const urlOrPath = `/dashboard/some_path`;
window.location.href= urlOrPath;

The href property of the Location interface is a stringifier that returns a string containing the whole URL, and allows the href to be updated.

Or:

const urlOrPath = `/dashboard/some_path`;
window.history.pushState({ someData: 'your data' }, 'unusedStr', urlOrPath);

The history.pushState() method adds an entry to the browser's session history stack.

Cassio Seffrin
  • 7,293
  • 1
  • 54
  • 54
-4

Hey I think you are in your production mode. That's why it is slow. But if you will host your site it will be pretty much like react only. But then also if you want to routing fast Then npm i next@4.2.3 --save will work fine..

tony
  • 1
  • 1
-5

to solve this issue followed the commands:

  1. yarn build/nmp build
  2. yarn start/npm start

I hope this will solve this issue