react-refresh-webpack-plugin: $RefreshReg$ is not defined with ChildCompiler usage
This is a follow up to https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/36#issuecomment-665036157.
I created a demo where you can reproduce the error: https://github.com/donaldpipowitch/react-refresh-webpack-plugin-RefreshSig-bug
It looks to happen because of a child compiler. I use html-webpack-plugin
to prerender a React component into an index.html
file. (This will render some placeholder graphics in our real app until the app has loaded completely.) Normally the template you use for html-webpack-plugin
can use all the loaders you have configured for the rest of your source code which is quite convenient. But I guess we’d need to disable ReactRefreshWebpackPlugin
for this somehow 🤔
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 47 (19 by maintainers)
Commits related to this issue
- Added the msg component and the app component to make sure that imports are working properly. There was of course a monster bug since webpack is hell :). Read [this](https://github.com/pmmmwh/react-re... — committed to acederberg/typescript-webpack5-react-template by acederberg 2 years ago
- Fixes: yarn build for the UI is throwing "Uncaught ReferenceError: $RefreshReg$ is not defined" #479 - Solution found here: https://github.com/pmmmwh/react-refresh-webpack-plugin/issues/176#issuecomm... — committed to MajorLift/typescript-fullstack-monorepo-starter by MajorLift a year ago
Storybook support fast refresh since 6.1 version 😉 Add this to
.storybook/main.js
I resolved the problem in such a way:
Yes, I do understand the frustration. It is an unfortunate constraint.
Though, I think you might be able to workaround this:
It is quite a hack, but for your purposes (i.e. code paths where HMR does not make sense share files with code paths where HMR is useful) it would suffice.
I had a somewhat relevant run-in with this “$RefreshReg$ is not defined” error, though my cause is not the same as the one OP mentions. I’m not sure where I should post this, but let me know if I should post this somewhere else. Just wanted to post in case someone else runs into this issue. For my project, developing with this plugin was great. It was only when I went to deploy this project to GCP that this “$RefreshReg$ is not defined” error occurred and prevented my app from loading at all – the screen was just blank. I’m using this plugin with the Typescript loader. The issue was resolved after I changed the conditional to only load the ReactRefreshTypescript plugin on my local environment. I made the following change:
to this:
Since react refresh is only really useful for local development anyway, I think it’s better to only include the plugin when on your local environment. I know the README checks to see if it is not the production env, but I feel like if you have multiple environments that you deploy to such as dev vs prod, then this plugin will be included when you try to build dev. In the end, this worked for me, so try this if you run into the “$RefreshReg$ is not defined” error and it isnt because of the OP’s reason.
I don’t think filtering out stuff is a problem when you share a Webpack config across multiple slightly varying setups? It is expected that some stuff don’t work for some particular setups. The error thrown is unfortunate but it also indicates that some part of the integration is broken. In an ideal world it would be up to us the plugin to inject the transform for you, but since Babel does not provide such an API at the moment we couldn’t to it.
Also to reiterate,
react-refresh/babel
is intentionally low level as its aim is to be used with integrations. When you eject from CR, it means that you will be maintaining the config to adopt to your various use cases. In that sense I think the docs are pretty clear that either you use this Webpack plugin together with the Babel plugin, or none - if you only use the Babel plugin not this Webpack plugin your app will likely crash.Side note - you would probably also want to enable this plugin and the Babel plugin when you SSR to gain the most benefit.
The problem is - the expected methods are stubs.
It is in place to allow overridable behaviour in any environment. It might be in a alternative JS environment where the
window
variable isundefined
, or maybe a web extension, electron or even a CLI. They could also - in this plugin’s case - be replaced by the compiler. If you check the actual produced code from this plugin forv0.4.x
onwards, there should be no call to$RefreshReg$
and$RefreshSig$
, but rather calls to__webpack_require__.$Refresh$.register
and__webpack_require__.$Refresh$.signature
.It is meant to be low level and crude so frameworks and compilers can do whatever optimisation they want.
A possible solution to my original problem: use a separated webpack compilation inside a compilation. (https://github.com/donaldpipowitch/react-refresh-webpack-plugin-RefreshSig-bug/pull/4/files, original idea from bebraw: https://github.com/styleguidist/mini-html-webpack-plugin/issues/39)
@pmmmwh Latest storybook show nothing because of refresh babel plugin 😦
https://github.com/storybookjs/storybook/issues/12396
It should be the same as Webpack automatically sets this to
true
. “Setting up your env variable without assignment,--env.production
sets--env.production
totrue
by default.”This is not really related to enabling/disabling this plugin - it’s more about the Babel plugin.
For example, if you intentionally exclude
react-refresh/babel
from being able to process the file you’d import from the html template your setup would be working fine. This is more of a “limitation” of what you can do with templating -html-webpack-plugin
inherits all the loaders but would not clone the plugins used, and does not allow you to add plugins to the pipeline without using their custom hooks (I’m not sure what is possible with them).The solution to this would be to exclude your entire code path from being processed by
react-refresh/babel
(for example you can use another instance ofbabel-loader
). Yes it is more config and it might be potentially expensive (depending on the project) but for stuff like that I think it warrants a separate Babel config: it is outside of your main bundle, served and consumed differently, and you don’t really need HMR for it?hello, i check it out every solution, but for this problem in my case, this is the best:
If you use react, just add this code in
public/index.html
page:and that’s all, it’s very simple and effective
I think a lot of the solutions posted in this thread are actually not related to the problem the OP is facing - they are just how you want to setup the Babel plugin and hooking it into your specific build pipeline, rather than disabling stuff or patching stuff in a constrained Webpack Child Compiler.
I’ll be closing this cause since solutions I can think of have been listed in the Troubleshooting Guide, and the unrelated solutions on this matter will really confuse people coming later.
If you still want to contribute to this issue/have a new way of dealing with it, feel free to open a PR against the guide and I will review it.
Shouldn’t prerendering be done in production mode?