repack icon indicating copy to clipboard operation
repack copied to clipboard

Repack v3 HMR breaks React Native inspector/devtools

Open bea73693 opened this issue 3 years ago • 1 comments

Environment

"@callstack/repack": "^3.0.0" "react-native": "0.70.1" node: v16.14.2 yarn: 1.22.19

Description

App throws error when attempting to access react native inspector (cmd+d) -> 'Show Inspector' and no inspection tools are available. After doing this the menu shows 'Hide Inspector' option and clicking this shows the same error.

Error in console: [Console] Invariant Violation: Expected to find at least one React Native renderer on DevTools hook., js engine: hermes

Error on device: Screen Shot 2022-09-27 at 12 14 38 PM

Disabling HMR in webpack.config.js shows the inspector as expected.

Reproducible Demo

  1. Init a new react native project, for example: npx react-native init test_app --template react-native-template-typescript
  2. Configure Repack according to https://re-pack.netlify.app/docs/getting-started#dependencies, using updated webpack config template under v3: https://github.com/callstack/repack/blob/v3/templates/webpack.config.cjs.
  3. Run repack, react-native webpack-start and run yarn ios --no-packager
  4. Open simulator menu (cmd+d) and click 'Show Inspector', error shown and no inspector tools available.
  5. Restart repack with lines 47-49 uncommented (sets HMR to false), open menu and inspector works as expected.

bea73693 avatar Sep 27 '22 17:09 bea73693

Seems like this issue was related to @pmmmwh/react-refresh-webpack-plugin v0.5.

I found two solutions:

  1. lock @pmmmwh/react-refresh-webpack-plugin to 0.4.3 by adding resolutions to package.json:
    "resolutions": {
        "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3"
    }
    
  2. Modify node_modules/react-devtools-core/dist/backend.js, search installHook function and remove target.hasOwnProperty check (first three lines.) And use patch-package to persistent changes.
     function installHook(target) {
    -    if (target.hasOwnProperty('__REACT_DEVTOOLS_GLOBAL_HOOK__')) {
    -        return null;
    -    }
    
         var targetConsole = console;
         var targetConsoleMethods = {};
    

jinliming2 avatar Oct 06 '22 10:10 jinliming2

In my tests, downgrading to 0.4.3 made the initial webpack builds much slower - so that wasn't an option, unfortunately.

Removing the target.hasOwnProperty() check from backend.js also didn't work - that allowed connecting to dev tools but broke HMR.

I think this has something to do with the patch made in https://github.com/callstack/repack/pull/1 to initialize devtools before react-refresh. (Specifically this block here) It seems to no longer work with the latest version of @pmmmwh/react-refresh-webpack-plugin.

My solution:

In https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/0610d3c11ee54733612eb1a8a12400cf42ed24c7/lib/index.js#L75, use the legacy logic for injecting the plugin:

-   if (EntryPlugin) {
+   if (false) {
      // Prepended entries does not care about injection order,
      // so we can utilise EntryPlugin for simpler logic.
      addEntries.prependEntries.forEach((entry) => {
        new EntryPlugin(compiler.context, entry, { name: undefined }).apply(compiler);
      });

By doing this, the patch to re-arrange the plugin initialization order is able to correctly find the refresh plugin, because it hits this block instead:

    } else {
      compiler.options.entry = injectRefreshEntry(compiler.options.entry, addEntries);
    }

There is probably a more correct way to do this (maybe change the code to find the react-refresh plugin to match the new EntryPlugin flow?), but I thought this would help point people down the right track.

sleeper-luke avatar Dec 02 '22 00:12 sleeper-luke

Seems like this issue was related to @pmmmwh/react-refresh-webpack-plugin v0.5.

I found two solutions:

  1. lock @pmmmwh/react-refresh-webpack-plugin to 0.4.3 by adding resolutions to package.json:
    "resolutions": {
        "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3"
    }
    
  2. Modify node_modules/react-devtools-core/dist/backend.js, search installHook function and remove target.hasOwnProperty check (first three lines.) And use patch-package to persistent changes.
     function installHook(target) {
    -    if (target.hasOwnProperty('__REACT_DEVTOOLS_GLOBAL_HOOK__')) {
    -        return null;
    -    }
    
         var targetConsole = console;
         var targetConsoleMethods = {};
    

also check if all the .lock file has same version of ["@pmmmwh/react-refresh-webpack-plugin": "^0.4.3"]. Remove other version of react-refresh-webpack-plugin in .lock files. [in All Mini App also]

suhassasuke avatar Feb 11 '24 05:02 suhassasuke