Description
Describe the bug
Please kindly note that this bug is not a duplicate of #10078.
Bug description
Prior to the addition of experimental support for fast-refresh (#8582), webpackHotDevClient would resort to reloading the page on HMR updates if it could not identify the updated module, or if an error occurred.
Such a behaviour was useful. Those situations occur frequently for people who eject and add Webpack plugins, eg. an asset not in mentioned in the JS entries was re-emitted, therefore not changing the compilation hash; or a loader writes an incorrect update JSON for an asset they emit (html-webpack-copy-plugin, in my case, is sending incorrect updates).
It's also possible for update errors to occur due to user code on non-ejected projects. We have a (proprietary) project where some JS files do not have a module.hot.accept
handler and generate HMR errors when updated. In those cases, we're happy to resort to reloading the page.
Root cause
Now, the following commit: c5b96c2#diff-fcdb901a67f29b1a0b22c42dbf36bb167c5262e2994675bd4d2650e8c4dd6c8aL246 introduced support for React Fast Refresh by disabling the force-reload if Fast Refresh is on.
function handleApplyUpdates(err, updatedModules) {
const hasReactRefresh = process.env.FAST_REFRESH;
const wantsForcedReload = err || !updatedModules || hadRuntimeError;
// React refresh can handle hot-reloading over errors.
if (!hasReactRefresh && wantsForcedReload) {
window.location.reload();
return;
}
This might be legitimate in the case where no updates were identified (!updatedModules
), or when there was a prior runtime error that could be fixed by the update (hadRuntimeError
) but I believe if an error was reported by Webpack's bootstrap script, Fast Refresh shouldn't be expected to work since the update information is reportedly incorrect.
I believe the following code would be more appropriate behaviour:
function handleApplyUpdates(webpackErr, updatedModules) {
const hasReactRefresh = process.env.FAST_REFRESH;
const wantsForcedReload = !updatedModules || hadRuntimeError;
// React refresh can handle hot-reloading over runtime errors.
if (webpackErr || (!hasReactRefresh && wantsForcedReload)) {
window.location.reload();
return;
}
Did you try recovering your dependencies?
- Dependencies up to date.
- yarn --version 1.22.10
Which terms did you search for in User Guide?
ø
Environment
Environment Info:
current version of create-react-app: 3.4.1
running from /home/steve/.config/yarn/global/node_modules/create-react-app
System:
OS: Linux 5.12 Arch Linux
CPU: (12) x64 Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz
Binaries:
Node: 16.3.0 - /usr/bin/node
Yarn: 1.22.10 - /usr/bin/yarn
npm: 7.16.0 - ~/Development/diplp-front-web/node_modules/.bin/npm
Browsers:
Chrome: Not Found
Firefox: 89.0
npmPackages:
react: ^17.0.2 => 17.0.2 (16.14.0)
react-dom: ^17.0.2 => 17.0.2
react-scripts: 4.0.1
npmGlobalPackages:
create-react-app: Not Found
Steps to reproduce
(Write your steps here:)
- Cause a HMR error (you can write a local file override of your webpack/bootstrap.js in your devTools and make the
request.onreadystatechange
handler always reject; sadly I can't share a MWE with systematic error behaviour at the moment) - Notice that the page does not refresh when a source file is updated
Expected behavior
The page should reload when a HMR error occurs, so that the update is applied nevertheless.
Actual behavior
The page does not automatically reload.
Reproducible demo
Sadly, my projects are my company's property and I'm unable to share them. There is significant boilerplate going into the projects where I can reproduce the bug, and I would need hours to extract a MWE and re-link all this code together in order to showcase the issue.
Errors can be somewhat easily simulated with a devtools override of http://localhost:3000/<projectAbsolutePathOnDisk>/webpack/bootstrap.js
.
- Open Devtools
- Go to Source tab
- In the leftside panel, next to pages, click on the double caret >>, and on the "Overrides" menu item
- Enable local overrides for the folder where the CRA project resides
- Press Ctrl+P and type "webpackbootstrap"
- Select the bootstrap matching the path of the CRA project if multiple entries are found
- In
equest.onreadystatechange
, near line 120, wherevar update = JSON.parse...
can be read, add areject('foo');
call - Reveal file in sidebar, right click it and choose 'save for overrides'