Skip to content

fix: skip terser-webpack-plugin versions that leave bundles unminified - #1444

Open
giaBaoJS wants to merge 1 commit into
callstack:mainfrom
giaBaoJS:fix/terser-plugin-bundle-assets
Open

fix: skip terser-webpack-plugin versions that leave bundles unminified#1444
giaBaoJS wants to merge 1 commit into
callstack:mainfrom
giaBaoJS:fix/terser-plugin-bundle-assets

Conversation

@giaBaoJS

Copy link
Copy Markdown

Summary

  • read the version of the resolved terser-webpack-plugin and only prefer the copy installed in the project root while it can still minify Re.Pack's .bundle assets
  • otherwise fall back to the copy shipped with Re.Pack, and warn about the version that was skipped
  • add getMinimizerConfig unit tests covering the selection

Why

terser-webpack-plugin 5.6.0 added per-minimizer asset filters, and its terser implementation declares filter = (name) => /\.[cm]?js(\?.*)?$/i.test(name). Re.Pack emits index.bundle and [name].chunk.bundle, so every asset is rejected by the filter and dropped before minification runs. Nothing is reported: no error, no warning, and the asset is not flagged [minimized] in stats. Production bundles simply ship unminified.

The report in #1390 attributes this to webpack internals missing under Rspack, but that is not the cause. Reproducing with the exact options Re.Pack passes, on a trivial entry, with only the plugin version changed:

bundler terser-webpack-plugin output
Rspack 1.6.0 5.5.0 210 bytes, minimized
Rspack 1.6.0 5.6.1 1347 bytes, not minimized, 0 errors, 0 warnings
webpack 5.105.4 5.5.0 16 bytes, minimized
webpack 5.105.4 5.6.1 351 bytes, not minimized, 0 errors, 0 warnings

So webpack users are affected too, and the fix should not be scoped to Rspack.

Pinning terser-webpack-plugin to 5.5.0 in packages/repack/package.json covers the fallback branch of getTerserPlugin, but not the root-first branch: a project that resolves 5.6.0 or newer at its own root still gets the silent no-op. That is the common case on pnpm and on hoisted layouts where another dependency pulls in a newer release.

Implementation notes

The version gate is expressed against terser-webpack-plugin, not against a bundler release, so it does not interact with the ongoing Rspack 2 work. When the version cannot be determined the plugin is assumed usable, which keeps the previous behaviour rather than failing a build over an unreadable manifest.

Closes #1390.

Validation

  • pnpm --filter @callstack/repack test: 34 suites, 303 tests passed
  • pnpm test: 10 tasks successful
  • pnpm typecheck, pnpm lint: clean
  • reverting only getMinimizerConfig.ts while keeping the new tests turns the two selection tests red on the assertion (the project's incompatible plugin is chosen), not on an import or compile error
  • end to end against the built package, Rspack, project root holding terser-webpack-plugin@5.6.1: before the change the asset is 1347 bytes and not minimized, after it is 210 bytes and minimized, with the fallback warning printed

terser-webpack-plugin 5.6.0 added per-minimizer asset filters and its terser
implementation only accepts `.js`, `.cjs` and `.mjs` files. Re.Pack emits
`.bundle` files, so every asset is filtered out before minification runs. No
error or warning is reported and production bundles ship unminified. This
affects both Rspack and webpack.

Read the version of the resolved plugin and keep preferring the copy installed
in the project root only while it can still minify Re.Pack's assets. Otherwise
fall back to the copy shipped with Re.Pack and warn about the version that was
skipped.
@vercel

vercel Bot commented Aug 24, 2026

Copy link
Copy Markdown

@giaBaoJS is attempting to deploy a commit to the Callstack Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot

changeset-bot Bot commented Aug 24, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2259ebd

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@callstack/repack Patch
@callstack/repack-plugin-expo-modules Patch
@callstack/repack-plugin-nativewind Patch
@callstack/repack-plugin-reanimated Patch
@callstack/repack-dev-server Patch
@callstack/repack-init Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Comment on lines +17 to +43
function isSupportedTerserPlugin({ version }: TerserPluginCandidate): boolean {
const coerced = version ? semver.coerce(version) : null;
// when the version cannot be determined, assume the plugin works
if (!coerced) return true;
return semver.lt(coerced, FIRST_UNSUPPORTED_TERSER_PLUGIN_VERSION);
}

function resolveTerserPluginVersion(options?: { paths: string[] }) {
try {
terserPluginPath = require.resolve('terser-webpack-plugin', {
paths: [rootDir],
});
const manifestPath = require.resolve(
'terser-webpack-plugin/package.json',
options
);
return (require(manifestPath) as { version: string }).version;
} catch {
terserPluginPath = require.resolve('terser-webpack-plugin');
return undefined;
}
}

function resolveTerserPluginCandidate(
paths?: string[]
): TerserPluginCandidate | undefined {
const options = paths ? { paths } : undefined;
try {
const pluginPath = require.resolve('terser-webpack-plugin', options);
return { pluginPath, version: resolveTerserPluginVersion(options) };
} catch {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wdyt about checking plugin’s actual capability instead of its manifest version?

terser-webpack-plugin/package.json may be hidden by an exports map (node docs), causing version to be undefined & affected plugin to be accepted.
since 5.6.x exposes filter that rejects .bundle files (source), could we load the candidate & check:

const filter = Plugin.terserMinify?.filter;
return typeof filter !== 'function' || filter('index.bundle') !== false;

this directly covers current & future versions, version can remain only for warning text

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Default minimizer silently no-ops with terser-webpack-plugin >= 5.6.0 under Rspack — production bundles ship unminified

2 participants