Environment
@callstack/repack: 5.2.5
@rspack/core: 1.7.0
terser-webpack-plugin: 5.6.1 (resolved from Re.Pack's own dependency range ^5.3.14)
- Node 24, React Native 0.83.9, monorepo with pnpm (isolated
node_modules)
Summary
Re.Pack's default minimizer (getMinimizerConfig → getTerserPlugin) prefers a project-root terser-webpack-plugin and falls back to the copy declared in Re.Pack's own dependencies (^5.3.14):
// dist/commands/common/config/getMinimizerConfig.js
try {
terserPluginPath = require.resolve('terser-webpack-plugin', { paths: [rootDir] });
} catch {
terserPluginPath = require.resolve('terser-webpack-plugin');
}
That range now resolves to 5.6.1, and terser-webpack-plugin >= 5.6.0 depends on webpack-only internals (e.g. compiler.webpack.javascript.JavascriptModulesPlugin.getCompilationHooks, ModuleFilenameHelpers.matchObject via compiler.webpack). Under Rspack it does nothing, without any error or warning — production bundles are emitted completely unminified (comments and whitespace included), and the asset is not marked [minimized] in stats.
The failure is easy to miss because of the resolution order:
- yarn / npm hoisted layouts: some other dependency often hoists an older
terser-webpack-plugin (5.3.x) to the workspace root, the root-first resolve picks it up, and everything works — by accident.
- pnpm / isolated layouts: nothing is hoisted to the root, the fallback resolves Re.Pack's own 5.6.1, and every production bundle silently ships unminified.
We hit this while migrating a Module Federation monorepo from yarn (hoisted) to pnpm: identical source, identical configs, and the remote expose chunks grew ~37–60% (e.g. 1.68 MB → 2.68 MB Hermes bytecode for one remote) with zero build errors. Bisecting the bundler pipeline eventually surfaced the minimizer no-op.
Reproduction (minimal A/B)
Same trivial entry, Rspack 1.7.0, mode: 'production', only the terser-webpack-plugin version differs in optimization.minimizer (using exactly the options Re.Pack passes):
new TerserPlugin({
test: /\.(js)?bundle(\?.*)?$/i,
extractComments: false,
terserOptions: { format: { comments: false } },
})
| terser-webpack-plugin |
output |
| 5.3.16 |
298 bytes, [minimized], mangled/compressed |
| 5.3.17 |
298 bytes, [minimized] |
| 5.4.0 |
298 bytes, [minimized] |
| 5.5.0 |
298 bytes, [minimized] |
| 5.6.0 |
1.24 KiB, untouched (comments/whitespace intact), no [minimized], no error |
| 5.6.1 |
1.24 KiB, untouched, no error |
So the break is exactly at 5.6.0.
Expected behavior
Either the bundles get minified, or the build fails loudly. A silent no-op in the production minimizer is the worst case — it shipped to our staging users unnoticed.
Suggested fixes
Any of these would prevent the silent regression:
- Constrain Re.Pack's dependency to
>=5.3.14 <5.6.0 (5.6.0 effectively dropped Rspack compatibility).
- When the bundler is Rspack, skip
terser-webpack-plugin resolution and use a known-good path (e.g. SwcJsMinimizerRspackPlugin, with whatever guard the 1.4.11-era issue requires).
- After the compilation, assert that production assets matching the minimizer
test carry info.minimized, and fail or warn otherwise.
The root-first require.resolve is also worth reconsidering: it makes behavior depend on what other packages happen to hoist into the workspace root, which is how this stayed hidden on yarn and only surfaced on pnpm.
Happy to provide the full repro repo if useful.
Environment
@callstack/repack: 5.2.5@rspack/core: 1.7.0terser-webpack-plugin: 5.6.1 (resolved from Re.Pack's own dependency range^5.3.14)node_modules)Summary
Re.Pack's default minimizer (
getMinimizerConfig→getTerserPlugin) prefers a project-rootterser-webpack-pluginand falls back to the copy declared in Re.Pack's own dependencies (^5.3.14):That range now resolves to 5.6.1, and
terser-webpack-plugin >= 5.6.0depends on webpack-only internals (e.g.compiler.webpack.javascript.JavascriptModulesPlugin.getCompilationHooks,ModuleFilenameHelpers.matchObjectviacompiler.webpack). Under Rspack it does nothing, without any error or warning — production bundles are emitted completely unminified (comments and whitespace included), and the asset is not marked[minimized]in stats.The failure is easy to miss because of the resolution order:
terser-webpack-plugin(5.3.x) to the workspace root, the root-first resolve picks it up, and everything works — by accident.We hit this while migrating a Module Federation monorepo from yarn (hoisted) to pnpm: identical source, identical configs, and the remote
exposechunks grew ~37–60% (e.g. 1.68 MB → 2.68 MB Hermes bytecode for one remote) with zero build errors. Bisecting the bundler pipeline eventually surfaced the minimizer no-op.Reproduction (minimal A/B)
Same trivial entry, Rspack 1.7.0,
mode: 'production', only theterser-webpack-pluginversion differs inoptimization.minimizer(using exactly the options Re.Pack passes):[minimized], mangled/compressed[minimized][minimized][minimized][minimized], no errorSo the break is exactly at 5.6.0.
Expected behavior
Either the bundles get minified, or the build fails loudly. A silent no-op in the production minimizer is the worst case — it shipped to our staging users unnoticed.
Suggested fixes
Any of these would prevent the silent regression:
>=5.3.14 <5.6.0(5.6.0 effectively dropped Rspack compatibility).terser-webpack-pluginresolution and use a known-good path (e.g.SwcJsMinimizerRspackPlugin, with whatever guard the 1.4.11-era issue requires).testcarryinfo.minimized, and fail or warn otherwise.The root-first
require.resolveis also worth reconsidering: it makes behavior depend on what other packages happen to hoist into the workspace root, which is how this stayed hidden on yarn and only surfaced on pnpm.Happy to provide the full repro repo if useful.