repack
repack copied to clipboard
Property 'HMRClient' doesn't exist
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.mjsin it's own terminal - run
react-native run-android --no-packagerin it's own terminal
App installs and presents following error on the emulated device
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.hmrtofalse. - Keep in mind that
devServerobject is not available - when running
webpack-bundlecommand. 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
envin your Babel config, you can remove it. - Keep in mind that if you remove it you should set
BABEL_ENVorNODE_ENV - to
developmentorproduction. 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,
},
}),
],
}; }; `
Sorry, but I resolved it by disabling HMR -_-,
In the ‘webpack.config.mjs’ file, replace:
hmr: devServer && devServer.hmr, -> hmr: false
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.
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.configplease replaceentry: [ ...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
WebpackHMRClientmight need some adjusting though.
this doesn't work for me
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.
@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',
},