why-did-you-render: Doesn't work with Vite + React

Hello ! I’m currently having troubles trying to use this library with my React project.

This is my wdyr.ts file:

/// <reference types="@welldone-software/why-did-you-render" />
import React from "react";

export default async function load () {
  if (process.env.NODE_ENV === "development") {
    // Importing because we can't require in Vite.
    const { default: whyDidYouRender } = await import("@welldone-software/why-did-you-render");

    whyDidYouRender(React, {
      trackAllPureComponents: true,
    });
  }
}

This is how I integrate it in my main.tsx (mountpoint)

import wdyr from "./wdyr";
await wdyr();

import React from "react";
import ReactDOM from "react-dom";

ReactDOM.render(
  <React.StrictMode>
    <AppRoutingAndMoreRightHere />
  </React.StrictMode>,
  document.getElementById("root")
);

When I run it, there isn’t any errors, but still it doesn’t work. I’ve also tried to add MyComponent.whyDidYouRender = true; but still have no effect.

By the way, I’m using vite 2.7.13 and react 17.0.2.

Hope you can help me with this !

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 2
  • Comments: 24

Most upvoted comments

Solution: vite.config.ts

export default defineConfig({
  plugins: [
    checker({ typescript: true }),
    svgr(),
    react({
      jsxImportSource: '@welldone-software/why-did-you-render', // <-----
    }),
  ],
  resolve: {
    alias: {
      // Needed for `useSelector` tracking in wdyr.tsx: https://github.com/welldone-software/why-did-you-render/issues/85
      'react-redux': 'react-redux/dist/react-redux.js',
    },
  },
});

wdyr.ts

/// <reference types="@welldone-software/why-did-you-render" />
import * as React from 'react';
import * as ReactRedux from 'react-redux';
import whyDidYouRender from '@welldone-software/why-did-you-render';

if (import.meta.env.DEV) {
  whyDidYouRender(React, {
    trackAllPureComponents: true,
    trackExtraHooks: [[ReactRedux, 'useSelector']],
  });
}

Edit: globEager cannot be used conditionally like I have it below, so for vite purposes my first example is still what we are using.


So it looks like instead we can leverage vite’s globEager (docs appear out of date since globEager is mentioned there as an option) usage to have this do what we want. We cannot use require with vite, and this issue is specific to vite.

main.tsx

/* eslint-disable import/first */
if (import.meta.env.DEV && import.meta.env.VITE_ENABLE_WHY_DID_YOU_RENDER === 'true') {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars
  const autoImport = import.meta.globEager('./wdyr.ts'); 
  // nothing needs to be done with this variable but one needs to be declared in order to import the module
}

wdyr.ts

import wdyr from '@welldone-software/why-did-you-render';
import * as React from 'react';

wdyr(React, {
  include: [/.*/],
  exclude: [/^BrowserRouter/, /^Link/, /^Route/],
  trackHooks: true,
  trackAllPureComponents: true,
});

That said, I believe that my original suggestion still works the same since the import './wdyr' line will be converted to a static require with vite, and then the import of wdyr should be completed synchronously before the rest of the code.

What’s working for me is the following

wdyr.ts

import * as React from 'react';

if (import.meta.env.DEV && import.meta.env.VITE_ENABLE_WHY_DID_YOU_RENDER === 'true') {
  const { default: wdyr } = await import('@welldone-software/why-did-you-render');

  wdyr(React, {
    include: [/.*/],
    exclude: [/^BrowserRouter/, /^Link/, /^Route/],
    trackHooks: true,
    trackAllPureComponents: true,
  });
}

main.tsx

// eslint-disable-next-line import/order
import './wdyr';

...

const root = createRoot(container);
root.render( ...

tsconfig.json

    "module": "ES2022",
    "target": "ES2017"

Despite using the above module/target browserlist provides a prod build time check to ensure I’m still using compatible features (aka I can’t ship code that’s using top-level await but I can use them behind a dev flag)

No trace of wdyr in the build output and works locally with the flag enabled.

this actually worked. @vzaidman could we add this to the documentation? PR’s welcome?

What’s working for me is the following

wdyr.ts

import * as React from 'react';

if (import.meta.env.DEV && import.meta.env.VITE_ENABLE_WHY_DID_YOU_RENDER === 'true') {
  const { default: wdyr } = await import('@welldone-software/why-did-you-render');

  wdyr(React, {
    include: [/.*/],
    exclude: [/^BrowserRouter/, /^Link/, /^Route/],
    trackHooks: true,
    trackAllPureComponents: true,
  });
}

main.tsx

// eslint-disable-next-line import/order
import './wdyr';

...

const root = createRoot(container);
root.render( ...

tsconfig.json

    "module": "ES2022",
    "target": "ES2017"

Despite using the above module/target browserlist provides a prod build time check to ensure I’m still using compatible features (aka I can’t ship code that’s using top-level await but I can use them behind a dev flag)

No trace of wdyr in the build output and works locally with the flag enabled.

I was able to get this working with vite by using the following

wydr.ts

import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';

if (process.env.NODE_ENV === 'development') {
  whyDidYouRender(React, {
    trackAllPureComponents: true,
  });
}

main.tsx

import './wdyr';
import React from 'react'
.
.
.

Then setting MyFunctionalComponent.whyDidYouRender = true

Doesn’t work for me as well

I played around a little bit with your sandbox and I, too, could not get it to work. Might be something with our configs, but what we have setup at my work seems to work with this tool.