vite-plugin-react icon indicating copy to clipboard operation
vite-plugin-react copied to clipboard

Could not Fast Refresh. Learn more at https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#consistent-components-exports

Open AlokTakshak opened this issue 10 months ago • 13 comments

Describe the bug

I am Working on a Mono Repo which has thousands line of code. Previously we were on Vite Version 4.4.9 and during that the plugin was working as expected we were not any hmr invalidate but after upgrading to Vite 5. Now once i update file which exports all messages that is used by all other files now my terminal is bombarded with thousands of hmr invalidate messages. Sample is attached. Could you help why started hapening now and how can we move to older behaviour. As fixing all files to decouple util function exports and React Components exports is not possible as code base more than 20,000+ files

Could not Fast Refresh ("getCascadingArchivalSelectionError" export is incompatible). Learn more at https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#consistent-components-exports 3:11:59 PM [vite] hmr update /File1.tsx, /File2.tsx 3:11:59 PM [vite] hmr invalidate /File2.utils.tsx Could not Fast Refresh ("getReplicationTargetSelectionError" export is incompatible). Learn more at https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#consistent-components-exports

Reproduction

NA

Steps to reproduce

Starting Dev server using vite --host

react({ jsxImportSource: '@emotion/react', babel: { plugins: ['@emotion/babel-plugin'], }, }),

System Info

System:
    OS: macOS 15.3
    CPU: (12) arm64 Apple M3 Pro
    Memory: 516.44 MB / 36.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.9.0 
    Yarn: 1.22.17 
    npm: 10.8.3 
    pnpm: 9.12.1 
  Browsers:
    Chrome: 132.0.6834.160
    Safari: 18.3
  npmPackages:
    @vitejs/plugin-react: 4.3.4 => 4.3.4
    @vitejs/plugin-react-swc: 3.3.0 => 3.3.0
    rollup: 4.30.1 => 4.30.1
    vite: 5.4.13 => 5.4.13

Used Package Manager

pnpm

Logs

No response

Validations

AlokTakshak avatar Feb 06 '25 09:02 AlokTakshak

This change was done in the version 3.1.0 of the plugin. Without that, updates to utils in your tsx files says "hmr update" but in fact the update is not available for others files

You have two solutions that to keep an half broken HMR:

  • Keep using the react-plugin v3.0.1 and ignore the vite peer deps range warning, it will work with Vite 2 to 6
  • Use latest version (better for perf) and have a local patch to change the line if (!nextExports) return; to return;.

Otherwise you can opt-out of HMR and use https://github.com/owlsdepartment/vite-plugin-babel with the emotion plugin or https://github.com/unplugin/unplugin-swc with the equivalent rust plugin (should have faster builds), but you get full page reload on every change. But at least you don't end up with an state where you need to manually refresh when doing some changes to non component exports

For info, at some point Vite will have a bundled dev mode where the react plugin can have HMR working despite having files that exports both utils and components, but it would take more than a year I think to get to it.

ArnaudBarre avatar Feb 06 '25 10:02 ArnaudBarre

@ArnaudBarre Thanks will try that

Use latest version (better for perf) and have a local patch to change the line if (!nextExports) return; to return;. can this change also be applied on @vitejs/plugin-react-swc as we have also have another project using @vitejs/plugin-react-swc

AlokTakshak avatar Feb 06 '25 10:02 AlokTakshak

Yes the HMR logic/code is exactly the same!

ArnaudBarre avatar Feb 06 '25 11:02 ArnaudBarre

@ArnaudBarre This does reduce the number of instances Could not Fast Refresh but while working with Vite 4.4.9 and latest version of @vitejs/plugin-react it refreshes whole page in cases where lots of invalidates were hapenning and but works normally when i was updating react components while after making above changes it doesn't even update UI when i am updating in a file which only exports React component. which i was not expecting. Do you think this could be due to change in Vite instead of Plugin?

AlokTakshak avatar Feb 06 '25 14:02 AlokTakshak

Sorry my bad, the patch skip the export checks, but also the fast refresh update. Instead of the suggested patch, delete this line below if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);

ArnaudBarre avatar Feb 06 '25 15:02 ArnaudBarre

Above change was not working expected as it was not triggering page refresh. I tried to find the root cause with @vitejs/[email protected] and [email protected] i don't see lots of hmr update but ui refreshes and gets updated which i was expecting after updating to [email protected] the above mentioned issue starts happening that is ui updates correctly but lots of hmr comments are added to both terminal console and dev console.

AlokTakshak avatar Feb 07 '25 11:02 AlokTakshak

I'm not sure I'm following. You are saying that with Vite 5 + latest version of the react plugin + a patch that remove if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage) you still have too many files updating with HMR?

ArnaudBarre avatar Feb 07 '25 13:02 ArnaudBarre

Project Structure we have a file known as generator.ts which read a file message.json and create a message.constants.ts. message.constants.ts exposes a MESSAGE Object which is imported by each file inside codebase and passed into id prop of FormattedMessage from react-intl

examples //File1.tsx ...... <FormattedMessage id={MESSAGE.BUTTONS.SUBMIT}/> //File12.tsx ...... <FormattedMessage id={MESSAGE.BUTTONS.CONTINUE}/> similarly each file is import the MESSAGE from message.constants.ts.

Now when i update text for Continue button in message.json the generator is triggered again and message.constants.ts is updated. Now expectation is that UI should also be updated with this new text.

@vitejs/[email protected] + [email protected] + (without removing if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage) ) -> This works as expected i.e we don't see many console logs and UI is also updated correctly

@vitejs/[email protected] + [email protected] + (without removing if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage) ) -> This updated the UI but we start seeing lots of hmr invalidated comments in both browser and terminal console

@vitejs/[email protected] + [email protected] + (with removing if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage) ) -> This fixes the hmr invalidated comments but Ui is not updated with the updated text.

AlokTakshak avatar Feb 10 '25 05:02 AlokTakshak

This seems weird. Did you try with a more recent version of Vite 5 or 6?

ArnaudBarre avatar Feb 27 '25 10:02 ArnaudBarre

@ArnaudBarre I did try this out was getting same error. Now we have taken an effort to fix all our files exportes to be consistent with https://www.npmjs.com/package/eslint-plugin-react-refresh During that also we are facing issues with if a file only have multiple hooks exports i am still seeing Could not Fast Refresh ("useXXXX" export is incompatible). Learn more at https://github.com/vitejs/vite-plugin-react-swc#consistent-components-exports Message. I couldn't find any documentation stating that you cant export multiple hooks is that expected? If there is some documentation arround what is allowed and what isn't could you point me towards that.

Thanks

AlokTakshak avatar Apr 21 '25 10:04 AlokTakshak

Does your hook files is in a tsx file? If there is no JSX in it you can rename it to .ts and it should make the issue go away, otherwise this is this main known issue: https://github.com/vitejs/vite-plugin-react/issues/354

I've been wanting to look deeper on fast refresh of hooks for more than a year know but never took the time to do it ...!

It this is not this, can you try to make a repro with https://vite.new/react-ts ?

ArnaudBarre avatar Apr 21 '25 10:04 ArnaudBarre

My Hooks Files does contains the JSX so creating a ts files won't be an options. I did Create a small repo here.

AlokTakshak avatar Apr 21 '25 16:04 AlokTakshak

So yeah this is the same issue as https://github.com/vitejs/vite-plugin-react/issues/354. You're the third person to report, I guess it's time to put work on that issue

ArnaudBarre avatar Apr 21 '25 22:04 ArnaudBarre

Does your hook files is in a tsx file? If there is no JSX in it you can rename it to .ts and it should make the issue go away, otherwise this is this main known issue: #354

I've been wanting to look deeper on fast refresh of hooks for more than a year know but never took the time to do it ...!

It this is not this, can you try to make a repro with https://vite.new/react-ts ?

This was my issue!

I had a react context/provider that was a tsx file that also had a hook in there. I moved the provider into a new file that fixed it for the provider. I was still seeing issues with the hooks and realized that my now hook-only file was still a .tsx extension. Renaming it to .ts fixed my issue.

The basic setup I assume when doing context/provider/hooks is to now have a minimum of 3 files.

/context.ts
/provider.tsx
/hooks.ts

This allows both the provider and hooks to consume from a context and keeps the imports clean.

nickzelei avatar May 07 '25 23:05 nickzelei

@nickzelei This is not exactly the same issue. The issue with context provider is a known limitation of the current setup of Fast Refresh in Vite, which requires two files: context + hook in one context.ts and provider.tsx

ArnaudBarre avatar May 08 '25 11:05 ArnaudBarre

@AlokTakshak good news I finally took some time to try out fast refresh for hooks and it didn't work as expected, but at least I opened a PR to avoid triggering these bad udpates for JSX hooks

ArnaudBarre avatar May 18 '25 15:05 ArnaudBarre

@ArnaudBarre Thanks for Fix.

AlokTakshak avatar May 22 '25 10:05 AlokTakshak