Turbopack: `productionBrowserSourceMaps: true` disables dead-import elimination for `compiler.define`-folded `typeof` guards
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 142k
- Forks
- 32.4k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 351
Description
Link to the code that reproduces this issue
https://github.com/kevbarns/turbopack-define-sourcemaps-repro
To Reproduce
npm install && npx next buildgrep -rl "FEATURE_MARKER_SHOULD_BE_TREESHAKEN" .next/static/chunks/
The repro has a local package (fake-sdk, sideEffects: false) that guards an import behind the universal SDK tree-shaking-flag pattern, with the flag set via compiler.define:
// fake-sdk/index.js
import { feature } from './feature.js'
function getDefaultIntegrations() {
const integrations = [];
if (typeof __MY_FLAG__ === 'undefined' || __MY_FLAG__) {
integrations.push(feature());
}
return integrations;
}
// next.config.mjs
const nextConfig = {
productionBrowserSourceMaps: true,
compiler: {
define: { __MY_FLAG__: false },
},
}
Current vs. Expected behavior
| Guard in the package | productionBrowserSourceMaps |
Dead module in the client bundle? |
|---|---|---|
typeof __MY_FLAG__ === 'undefined' || __MY_FLAG__ |
not set | pruned ✔ |
typeof __MY_FLAG__ === 'undefined' || __MY_FLAG__ |
true |
bundled ✗ (this issue) |
if (__MY_FLAG__) |
true |
pruned ✔ |
Expected: enabling browser source maps should not change which modules are considered live. The guarded branch is dead either way (the call site is correctly eliminated from the emitted code in all cases) — but with source maps enabled, the import it referenced is kept in the module graph and the whole subtree is emitted.
Reproduced on next 16.3.0, 16.3.2 and 16.4.0-canary.3.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.5.0
Available memory (MB): 65536
Available CPU cores: 14
Binaries:
Node: 24.11.1
npm: 11.6.2
Relevant Packages:
next: 16.4.0-canary.3 // also reproduced on 16.3.0 and 16.3.2
react: 19.2.4
react-dom: 19.2.4
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Turbopack, Performance
Additional context
Real-world impact: typeof __FLAG__ === 'undefined' || __FLAG__ is the universal guard used by SDK tree-shaking flags — e.g. Sentry's __SENTRY_TRACING__ / __SENTRY_DEBUG__ (which the Sentry docs suggest wiring through compiler.define on Turbopack). Sentry users are hit by the combination almost by definition: they enable productionBrowserSourceMaps precisely to upload source maps to Sentry, which silently makes the flags inoperative. On our production Next.js app this keeps ~30 KB minified of unreachable tracing code in the first load. Downstream report with measurements: https://github.com/getsentry/sentry-javascript/issues/23482
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked reproduction, especially fake-sdk/index.js and next.config.mjs, then run npm install && npx next build and grep the generated chunks for FEATURE_MARKER_SHOULD_BE_TREESHAKEN. Trace the Turbopack build behavior with productionBrowserSourceMaps enabled; done means the guarded module subtree is absent from the client bundle while source maps remain enabled.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, nextjs
- Domain
- build-system, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100