repack icon indicating copy to clipboard operation
repack copied to clipboard

Property 'HMRClient' doesn't exist

Open mikeFromUDig opened this issue 1 year ago • 2 comments

Environment

  • Windows 11
  • "react": "18.2.0",
  • "react-native": "0.73.4"
  • targeting Android platform
  • "@callstack/repack": "^3.7.0",
  • "webpack": "^5.90.1"
  • "terser-webpack-plugin": "^5.3.10",

Description

Running into this issue on my windows local environment. Any help would be appreciated

Run steps:

  • run react-native webpack-start --host 127.0.0.1 --webpackConfig ./webpack.config.mjs in it's own terminal
  • run react-native run-android --no-packager in it's own terminal

App installs and presents following error on the emulated device image

Reproducible Demo

##Webpack Config `import path from 'path'; import TerserPlugin from 'terser-webpack-plugin'; import * as Repack from '@callstack/repack';

/**

  • More documentation, installation, usage, motivation and differences with Metro is available at:
  • https://github.com/callstack/repack/blob/main/README.md
  • The API documentation for the functions and plugins used in this file is available at:
  • https://re-pack.netlify.app/ */

/**

  • Webpack configuration.
  • You can also export a static object or a function returning a Promise.
  • @param env Environment options passed from either Webpack CLI or React Native CLI
  •        when running with `react-native start/bundle`.
    

*/ export default (env) => { const { mode = 'development', context = Repack.getDirname(import.meta.url), entry = './index.js', platform = process.env.PLATFORM, minimize = mode === 'production', devServer = undefined, bundleFilename = undefined, sourceMapFilename = undefined, assetsPath = undefined, reactNativePath = new URL('./node_modules/react-native', import.meta.url) .pathname, } = env; const dirname = Repack.getDirname(import.meta.url);

if (!platform) { throw new Error('Missing platform'); }

/**
  • Using Module Federation might require disabling hmr.
  • Uncomment below to set devServer.hmr to false.
  • Keep in mind that devServer object is not available
  • when running webpack-bundle command. Be sure
  • to check its value to avoid accessing undefined value,
  • otherwise an error might occur. */ // if (devServer) { // devServer.hmr = false; // }

/**

  • Depending on your Babel configuration you might want to keep it.
  • If you don't use env in your Babel config, you can remove it.
  • Keep in mind that if you remove it you should set BABEL_ENV or NODE_ENV
  • to development or production. Otherwise your production code might be compiled with
  • in development mode by Babel. */ process.env.BABEL_ENV = mode;

return { mode, /** * This should be always false, since the Source Map configuration is done * by SourceMapDevToolPlugin. / devtool: false, context, /* * getInitializationEntries will return necessary entries with setup and initialization code. * If you don't want to use Hot Module Replacement, set hmr option to false. By default, * HMR will be enabled in development mode. / entry: [ ...Repack.getInitializationEntries(reactNativePath, { hmr: devServer && devServer.hmr, }), entry, ], resolve: { /* * getResolveOptions returns additional resolution configuration for React Native. * If it's removed, you won't be able to use <file>.<platform>.<ext> (eg: file.ios.js) * convention and some 3rd-party libraries that specify react-native field * in their package.json might not work correctly. */ ...Repack.getResolveOptions(platform),

  /**
   * Uncomment this to ensure all `react-native*` imports will resolve to the same React Native
   * dependency. You might need it when using workspaces/monorepos or unconventional project
   * structure. For simple/typical project you won't need it.
   */
  // alias: {
  //   'react-native': reactNativePath,
  // },
},
/**
 * Configures output.
 * It's recommended to leave it as it is unless you know what you're doing.
 * By default Webpack will emit files into the directory specified under `path`. In order for the
 * React Native app use them when bundling the `.ipa`/`.apk`, they need to be copied over with
 * `Repack.OutputPlugin`, which is configured by default inside `Repack.RepackPlugin`.
 */
output: {
  clean: true,
  hashFunction: 'xxhash64',
  path: path.resolve(dirname, 'build/generated', platform),
  filename: 'index.bundle',
  chunkFilename: '[name].chunk.bundle',
  publicPath: Repack.getPublicPath({ platform, devServer }),
},
/**
 * Configures optimization of the built bundle.
 */
optimization: {
  /** Enables minification based on values passed from React Native CLI or from fallback. */
  minimize,
  /** Configure minimizer to process the bundle. */
  minimizer: [
    new TerserPlugin({
      test: /\.(js)?bundle(\?.*)?$/i,
      /**
       * Prevents emitting text file with comments, licenses etc.
       * If you want to gather in-file licenses, feel free to remove this line or configure it
       * differently.
       */
      extractComments: false,
      terserOptions: {
        format: {
          comments: false,
        },
      },
    }),
  ],
  chunkIds: 'named',
},
module: {
  /**
   * This rule will process all React Native related dependencies with Babel.
   * If you have a 3rd-party dependency that you need to transpile, you can add it to the
   * `include` list.
   *
   * You can also enable persistent caching with `cacheDirectory` - please refer to:
   * https://github.com/babel/babel-loader#options
   */
  rules: [
    {
      test: /\.[jt]sx?$/,
      include: [
        /node_modules(.*[/\\])+react\//,
        /node_modules(.*[/\\])+react-native/,
        /node_modules(.*[/\\])+@react-native/,
        /node_modules(.*[/\\])+@react-navigation/,
        /node_modules(.*[/\\])+@react-native-community/,
        /node_modules(.*[/\\])+expo/,
        /node_modules(.*[/\\])+pretty-format/,
        /node_modules(.*[/\\])+metro/,
        /node_modules(.*[/\\])+abort-controller/,
        /node_modules(.*[/\\])+@callstack\/repack/,
      ],
      use: 'babel-loader',
    },
    /**
     * Here you can adjust loader that will process your files.
     *
     * You can also enable persistent caching with `cacheDirectory` - please refer to:
     * https://github.com/babel/babel-loader#options
     */
    {
      test: /\.[jt]sx?$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          /** Add React Refresh transform only when HMR is enabled. */
          plugins:
            devServer && devServer.hmr
              ? ['module:react-refresh/babel']
              : undefined,
        },
      },
    },
    /**
     * This loader handles all static assets (images, video, audio and others), so that you can
     * use (reference) them inside your application.
     *
     * If you wan to handle specific asset type manually, filter out the extension
     * from `ASSET_EXTENSIONS`, for example:
     * ```
     * Repack.ASSET_EXTENSIONS.filter((ext) => ext !== 'svg')
     * ```
     */
    {
      test: Repack.getAssetExtensionsRegExp(Repack.ASSET_EXTENSIONS),
      use: {
        loader: '@callstack/repack/assets-loader',
        options: {
          platform,
          devServerEnabled: Boolean(devServer),
          /**
           * Defines which assets are scalable - which assets can have
           * scale suffixes: `@1x`, `@2x` and so on.
           * By default all images are scalable.
           */
          scalableAssetExtensions: Repack.SCALABLE_ASSETS,
        },
      },
    },
  ],
},
plugins: [
  /**
   * Configure other required and additional plugins to make the bundle
   * work in React Native and provide good development experience with
   * sensible defaults.
   *
   * `Repack.RepackPlugin` provides some degree of customization, but if you
   * need more control, you can replace `Repack.RepackPlugin` with plugins
   * from `Repack.plugins`.
   */
  new Repack.RepackPlugin({
    context,
    mode,
    platform,
    devServer,
    output: {
      bundleFilename,
      sourceMapFilename,
      assetsPath,
    },
  }),
],

}; }; `

mikeFromUDig avatar Feb 12 '24 20:02 mikeFromUDig

Sorry, but I resolved it by disabling HMR -_-,

In the ‘webpack.config.mjs’ file, replace: hmr: devServer && devServer.hmr, -> hmr: false

vinhmdev avatar Feb 24 '24 07:02 vinhmdev

hi @mikeFromUDig

I don't have access to a Windows machine atm, but I have an idea what might be happening, can you try doing the following:

In webpack.config please replace

entry: [
  ...Repack.getInitializationEntries(reactNativePath, {
    hmr: devServer && devServer.hmr,
  }),
  entry,
],

with

entry: [
  ...Repack.getInitializationEntries(reactNativePath, {
    hmr: false,
  }),
  path.resolve('@callstack/repack/modules/WebpackHMRClient.js'),
  entry,
],

Please see if that works. The path to WebpackHMRClient might need some adjusting though.

jbroma avatar Feb 29 '24 13:02 jbroma

hi @mikeFromUDig

I don't have access to a Windows machine atm, but I have an idea what might be happening, can you try doing the following:

In webpack.config please replace

entry: [
  ...Repack.getInitializationEntries(reactNativePath, {
    hmr: devServer && devServer.hmr,
  }),
  entry,
],

with

entry: [
  ...Repack.getInitializationEntries(reactNativePath, {
    hmr: false,
  }),
  path.resolve('@callstack/repack/modules/WebpackHMRClient.js'),
  entry,
],

Please see if that works. The path to WebpackHMRClient might need some adjusting though.

this doesn't work for me

peterbd avatar Mar 14 '24 07:03 peterbd

This issue has been marked as stale because it has been inactive for 30 days. Please update this issue or it will be automatically closed in 14 days.

github-actions[bot] avatar Apr 14 '24 00:04 github-actions[bot]

@mikeFromUDig @vinhmdev @peterbd found the root issue.

to resolve the error in question please adjust the path of @callstack/repack inside of module.rules in webpack.config.mjs like this:

diff --git a/templates/webpack.config.mjs b/templates/webpack.config.mjs
index 18313be..e702a00 100644
--- a/templates/webpack.config.mjs
+++ b/templates/webpack.config.mjs
@@ -159,7 +159,7 @@ export default (env) => {
             /node_modules(.*[/\\])+pretty-format/,
             /node_modules(.*[/\\])+metro/,
             /node_modules(.*[/\\])+abort-controller/,
-            /node_modules(.*[/\\])+@callstack\/repack/,
+            /node_modules(.*[/\\])+@callstack[/\\]repack/,
           ],
           use: 'babel-loader',
         },

jbroma avatar Apr 16 '24 15:04 jbroma