Create-react-app: v4.0.0-next.77 hot reloading regression from v3

Created on 23 Aug 2020  路  6Comments  路  Source: facebook/create-react-app

Describe the bug

I have an app where I dynamically import an HTML file and load that into the document. In version 3, changing the HTML file would trigger a refresh no problem, but in version 4 that no longer happens.

Interestingly it does recompile (the output changes to "Compiling..." for a moment) on save, but the new content is not available.

Did you try recovering your dependencies?

$ npm version
6.14.7

Which terms did you search for in User Guide?

Fast refresh, hot reloading

Environment

$ npx create-react-app --info
npx: installed 98 in 5.514s

Environment Info:

  current version of create-react-app: 3.4.1
  running from /Users/kentcdodds/.npm/_npx/28053/lib/node_modules/create-react-app

  System:
    OS: macOS 10.15.6
    CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
  Binaries:
    Node: 14.4.0 - ~/n/bin/node
    Yarn: Not Found
    npm: 6.14.7 - /usr/local/bin/npm
  Browsers:
    Chrome: 84.0.4147.135
    Firefox: 77.0.1
    Safari: 13.1.2
  npmPackages:
    react: ^16.13.1 => 16.13.1 
    react-dom: ^16.13.1 => 16.13.1 
    react-scripts: ^4.0.0-next.77 => 4.0.0-next.77 
  npmGlobalPackages:
    create-react-app: Not Found

Steps to reproduce

I'm still working on a simple way to reproduce. Will update this here soon.

Expected behavior

I expect changing the file to trigger a refresh of the browser

Actual behavior

Nothing on the page changes until I refresh the browser manually

Reproducible demo

https://github.com/kentcdodds/react-fundamentals

  1. Go to: http://localhost:3000/1 or http://localhost:3000/isolated/exercise/01.html
  2. Open src/exercise/01.html
  3. Make any change and notice nothing refreshes
bug report needs triage

Most helpful comment

I have had a quick look in the original mentioned repository and when I add a bunch of logs left and right. Looks like the change is detected but because the status of HMR is abort the status won't be applied as the line:

if (!isUpdateAvailable() || !canApplyUpdates()) {

is triggered so the function is exited because canApplyUpdated() returns false so it enters this if-block. I am not sure why the status is abort though.

Some of the logs which get triggered when changing the html file and then save it:

onmessage() message:  {type: "invalid"}
webpackHotDevClient.js:207 onmessage() message:  {type: "invalid"}
webpackHotDevClient.js:207 onmessage() message:  {type: "invalid"}
webpackHotDevClient.js:207 onmessage() message:  {type: "invalid"}
webpackHotDevClient.js:207 onmessage() message:  {type: "hash", data: "8761994698881b8f5d7a"}
webpackHotDevClient.js:198 handleAvailableHash() 8761994698881b8f5d7a
webpackHotDevClient.js:207 onmessage() message:  {type: "hash", data: "8761994698881b8f5d7a"}
webpackHotDevClient.js:198 handleAvailableHash() 8761994698881b8f5d7a
webpackHotDevClient.js:207 onmessage() message:  {type: "ok"}
webpackHotDevClient.js:100 handleSuccess()
webpackHotDevClient.js:89 clearOutdatedErrors()
webpackHotDevClient.js:109 handleSuccess() isHotUpdate!!
webpackHotDevClient.js:248 tryApplyUpdates() onHotUpdateSuccess:  茠 onHotUpdateSuccess() {
      // Only dismiss it when we're sure it's a hot update.
      // Otherwise it would flicker right before the reload.
      tryDismissErrorOverlay();
    }
webpackHotDevClient.js:236 isUpdateAvailable()
webpackHotDevClient.js:257 tryApplyUpdates() isUpdateAvailable:  true
webpackHotDevClient.js:242 canApplyUpdates() status:  idle
webpackHotDevClient.js:258 tryApplyUpdates() canApplyUpdates:  true
webpackHotDevClient.js:236 isUpdateAvailable()
webpackHotDevClient.js:242 canApplyUpdates() status:  idle
webpackHotDevClient.js:207 onmessage() message:  {type: "ok"}
webpackHotDevClient.js:100 handleSuccess()
webpackHotDevClient.js:89 clearOutdatedErrors()
webpackHotDevClient.js:109 handleSuccess() isHotUpdate!!
webpackHotDevClient.js:248 tryApplyUpdates() onHotUpdateSuccess:  茠 onHotUpdateSuccess() {
      // Only dismiss it when we're sure it's a hot update.
      // Otherwise it would flicker right before the reload.
      tryDismissErrorOverlay();
    }
webpackHotDevClient.js:236 isUpdateAvailable()
webpackHotDevClient.js:257 tryApplyUpdates() isUpdateAvailable:  true
webpackHotDevClient.js:242 canApplyUpdates() status:  abort
webpackHotDevClient.js:258 tryApplyUpdates() canApplyUpdates:  false
webpackHotDevClient.js:236 isUpdateAvailable()
webpackHotDevClient.js:242 canApplyUpdates() status:  abort
webpackHotDevClient.js:260 tryApplyUpdates() !isUpdateAvailable || !canApplyUpdates
webpackHotDevClient.js:236 isUpdateAvailable()

All 6 comments

Alrighty, here's a minimal reproduction. Pretty simple: https://github.com/kentcdodds/react-scripts-hot-reloading-raw-loader

// eslint-disable-next-line import/no-webpack-loader-syntax
import html from '!raw-loader!./example.html'
document.body.innerHTML = html

I realize that there is no intended support of raw-loader, so if this gets closed for that reason I guess I can accept that and I'll try to find a workaround. But it would be cool if we could find a way to get a refresh for this case.

I have had a quick look in the original mentioned repository and when I add a bunch of logs left and right. Looks like the change is detected but because the status of HMR is abort the status won't be applied as the line:

if (!isUpdateAvailable() || !canApplyUpdates()) {

is triggered so the function is exited because canApplyUpdated() returns false so it enters this if-block. I am not sure why the status is abort though.

Some of the logs which get triggered when changing the html file and then save it:

onmessage() message:  {type: "invalid"}
webpackHotDevClient.js:207 onmessage() message:  {type: "invalid"}
webpackHotDevClient.js:207 onmessage() message:  {type: "invalid"}
webpackHotDevClient.js:207 onmessage() message:  {type: "invalid"}
webpackHotDevClient.js:207 onmessage() message:  {type: "hash", data: "8761994698881b8f5d7a"}
webpackHotDevClient.js:198 handleAvailableHash() 8761994698881b8f5d7a
webpackHotDevClient.js:207 onmessage() message:  {type: "hash", data: "8761994698881b8f5d7a"}
webpackHotDevClient.js:198 handleAvailableHash() 8761994698881b8f5d7a
webpackHotDevClient.js:207 onmessage() message:  {type: "ok"}
webpackHotDevClient.js:100 handleSuccess()
webpackHotDevClient.js:89 clearOutdatedErrors()
webpackHotDevClient.js:109 handleSuccess() isHotUpdate!!
webpackHotDevClient.js:248 tryApplyUpdates() onHotUpdateSuccess:  茠 onHotUpdateSuccess() {
      // Only dismiss it when we're sure it's a hot update.
      // Otherwise it would flicker right before the reload.
      tryDismissErrorOverlay();
    }
webpackHotDevClient.js:236 isUpdateAvailable()
webpackHotDevClient.js:257 tryApplyUpdates() isUpdateAvailable:  true
webpackHotDevClient.js:242 canApplyUpdates() status:  idle
webpackHotDevClient.js:258 tryApplyUpdates() canApplyUpdates:  true
webpackHotDevClient.js:236 isUpdateAvailable()
webpackHotDevClient.js:242 canApplyUpdates() status:  idle
webpackHotDevClient.js:207 onmessage() message:  {type: "ok"}
webpackHotDevClient.js:100 handleSuccess()
webpackHotDevClient.js:89 clearOutdatedErrors()
webpackHotDevClient.js:109 handleSuccess() isHotUpdate!!
webpackHotDevClient.js:248 tryApplyUpdates() onHotUpdateSuccess:  茠 onHotUpdateSuccess() {
      // Only dismiss it when we're sure it's a hot update.
      // Otherwise it would flicker right before the reload.
      tryDismissErrorOverlay();
    }
webpackHotDevClient.js:236 isUpdateAvailable()
webpackHotDevClient.js:257 tryApplyUpdates() isUpdateAvailable:  true
webpackHotDevClient.js:242 canApplyUpdates() status:  abort
webpackHotDevClient.js:258 tryApplyUpdates() canApplyUpdates:  false
webpackHotDevClient.js:236 isUpdateAvailable()
webpackHotDevClient.js:242 canApplyUpdates() status:  abort
webpackHotDevClient.js:260 tryApplyUpdates() !isUpdateAvailable || !canApplyUpdates
webpackHotDevClient.js:236 isUpdateAvailable()

Following on from @weyert 's excellent detective work, here's the error that is causing the abort status:

Error: Aborted because ./node_modules/raw-loader/dist/cjs.js!./src/exercise/01.html is not accepted
Update propagation: ./node_modules/raw-loader/dist/cjs.js!./src/exercise/01.html -> ./src/index.js -> 1
    at hotApplyInternal (bootstrap:558)
    at hotApply (bootstrap:412)
    at bootstrap:387

It could just be that as you theorize, raw-loader is not supported but I'm intrigued to have a little look further 馃憖

raw-loader was supported in previous versions, so if it's no longer supported that's either a regression or a breaking change. (Not a breaking change for CRA because technically inline loaders isn't supported. I mean a breaking change for raw-loader or webpack).

a little workaround is to use this

if (module.hot) {
  module.hot.accept()
}

in your index.js file

Maybe the problem is causing by the new webpack plugin that CRA is using fast-refresh

Considering inline loaders aren't technically supported, that's a satisfactory solution. Thanks @marcofugaro!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

oltsa picture oltsa  路  3Comments

alleroux picture alleroux  路  3Comments

Aranir picture Aranir  路  3Comments

onelson picture onelson  路  3Comments

rdamian3 picture rdamian3  路  3Comments