Skip to content

Minifier silently drops text when constant-folding tpl + tpl concatenation — broken on all stable releases, fixed in 16.3.0-canary.59 (backport request) #95900

Description

@noamtal21

Link to the code that reproduces this issue

https://github.com/noamtal21/next-swc-template-concat-repro

To Reproduce

  1. pnpm install && pnpm build (Turbopack; next build --webpack reproduces identically — the shared SWC minifier is at fault)
  2. grep -o '.\{40\}0 0 640 400.\{60\}' .next/server/chunks/*.js
  3. Or at runtime: pnpm start, then curl localhost:3000/variants — a route that self-reports which concatenation shapes were miscompiled.

No build needed — the bug is reachable directly through Next's vendored minifier:

const b = await require('next/dist/build/swc').loadBindings();
const src = 'const W=640,H=400; export function f(o){ return `A${W}B${H}LTAIL>` + `<r ${W}RTAIL>` + o; }';
(await b.minify(src, { compress: true, mangle: false, module: true })).code
// next 16.2.10:          'export function f(o){return"A640B400<r 640RTAIL>"+o}'      ← LTAIL> silently dropped
// next 16.3.0-canary.59: 'export function f(o){return"A640B400LTAIL><r 640RTAIL>"+o}' ← correct

Current vs. Expected behavior

When production minification constant-folds a concatenation of two template literals that each contain an interpolation, the text after the left template's last interpolation is silently dropped.

Source:

const WIDTH = 640, HEIGHT = 400;
return Buffer.from(
  `<svg width="${WIDTH}" height="${HEIGHT}" viewBox="0 0 ${WIDTH} ${HEIGHT}" xmlns="http://www.w3.org/2000/svg">` +
  `<rect width="${WIDTH}" height="${HEIGHT}" fill="#18181b"/>` +
  overlay +
  `</svg>`
);

Emitted chunk — the entire " xmlns="http://www.w3.org/2000/svg"> segment is gone:

Buffer.from('<svg width="640" height="400" viewBox="0 0 640 400<rect width="640" height="400" fill="#18181b"/>'+e+"</svg>")

Expected: the folded string preserves every quasi. The output is wrong but syntactically valid, so the build succeeds and the corruption only surfaces in production behavior (in our case: every server-generated SVG thumbnail became malformed — viewBox="0 0 640 400<rect).

Trigger matrix (from lib/variants.js in the repro; each left template ends in a LTAIL_n> marker):

Shape Result
`a${C}tail` + `b${C}c` (const interpolations both sides) corrupted — tail dropped
interpolation on only one side, or tpl + 'plain' / 'plain' + tpl ok
non-constant interpolation on either side (no folding) ok
single template literal (the workaround) ok

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 24.5.0
  Available memory (MB): 16384
  Available CPU cores: 10
Binaries:
  Node: 24.11.1
  npm: 11.6.2
  pnpm: 10.22.0
Relevant Packages:
  next: 16.2.10 // latest stable — still broken; fixed only on canary
  react: 19.2.3
  react-dom: 19.2.3
Next.js Config:
  output: N/A

Which area(s) are affected? (leave empty if unsure)

SWC, Turbopack, Webpack (production minification under both bundlers)

Additional context

Root cause is the upstream SWC bug fixed in swc-project/swc#11939 (merged 2026-06-15): the Tpl + Tpl branch of concat_tpl merges the boundary quasis' raw but not cooked; downstream evaluation (eval_tpl_as_str etc.) reads cooked, so the left template's final quasi vanishes. The fix reached Next.js via the swc 70 upgrade (#94814) — bisected to 16.3.0-canary.59 (canary.58 is broken, canary.59 is fixed).

Verified affected range (via the loadBindings().minify one-liner): 15.5.20 (current backport line), 16.0.0, 16.1.5, 16.2.10 (current latest) are all broken; 16.3.0-canary.59+ is fixed.

Filing even though canary is already fixed because this is silent output corruption on every currently installable stable release — could the swc 70 bump (or a cherry-pick of swc-project/swc#11939) be considered for backport to 16.2.x / 15.5.x?

Workaround for affected versions: write the concatenation as a single template literal.

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions