Search code examples
reactjsnext.jsbabeljsrerenderswc-compiler

How to configure Why Did You Render with NextJS 12


Next.JS uses babel to configure the Why Did You Render.

module.exports = function (api) {
    const isServer = api.caller((caller) => caller?.isServer)
    const isCallerDevelopment = api.caller((caller) => caller?.isDev)

    const presets = [
        [
            'next/babel',
            {
                'preset-react': {
                    importSource:
                        !isServer && isCallerDevelopment
                            ? '@welldone-software/why-did-you-render'
                            : 'react'
                }
            }
        ]
    ]

    return {presets}
}

How can this be updated to Next.JS 12 without disabling SWC?


Solution

  • After experimenting a bit, I came to the final conclusion:

    You can do it via next.config.js configuration, which doesn't disable SWC, but there are a few things you should take care of:

    • First you need to stop the devserver entirely;
    • Then you have to wipe .next folder or whatever path is your build;
    • Finally, create a folder called scripts, and create a file named whyDidYouRender.js inside it.

    Now edit your config file

    // next.config.js:
    const path = require('path');
    
    module.exports = {
      /**
       * @param {{[key: string]: unknown}} config
       * @param {{isDev: boolean; isServer: boolean;}} options
       */
      webpack(config, { dev, isServer }) {
        // why did you render
        if (dev && !isServer) {
          const originalEntry = config.entry;
          config.entry = async () => {
            const wdrPath = path.resolve(__dirname, './scripts/whyDidYouRender.js')
            const entries = await originalEntry();
            if (entries['main.js'] && !entries['main.js'].includes(wdrPath)) {
              entries['main.js'].unshift(wdrPath);
            }
            return entries;
          };
        }
    
        return config;
      },
    };
    

    And edit whyDidYouRender file

    // scripts/whyDidYouRender.js
    import React from 'react';
    
    if (process.env.NODE_ENV === 'development') {
      // eslint-disable-next-line
        const whyDidYouRender = require('@welldone-software/why-did-you-render');
      // @ts-ignore
      whyDidYouRender(React, {
        trackAllPureComponents: true,
      });
    }
    
    

    If you still have trouble, you can replace this line:

    if (process.env.NODE_ENV === 'development')

    with

    if (process.env.NODE_ENV === 'development' && typeof window === 'object')

    Or you can remove this check entirely, since this file is only supposed to be imported if webpack's option dev is true and option isServer is false

    PS.: Please note that why-did-you-render may run silently if there are no issues, so no console messages doesn't necessarily means it's not running. You can create an issue to test it