Skip to content

Commit 4b8a9e0

Browse files
NullVoxPopuliclaude
andcommitted
rollup: mark @glimmer/debug{,-util,-flags} as side-effect-free in treeshake
Each of these packages already declares \`sideEffects: false\` in its own \`package.json\`, but that declaration is lost the moment rollup bundles their source files into shared chunks alongside other-package runtime code. Once that happens, downstream bundlers (vite/rolldown consuming ember-source's dist/prod) load the chunk for any runtime symbol from another package and end up evaluating the debug top-level (e.g. the \`STYLES\` const, \`LogFragmentBuffer\` class definitions, ANNOTATION_STYLES array) — even though every actual call site is behind \`if (LOCAL_DEBUG) {…}\` and gets DCE'd by Babel. Add a \`treeshake.moduleSideEffects\` callback to the shared ESM rollup config that explicitly marks files under those three packages as pure. Anything else stays default (conservative). Result: the \`render/styles.ts\` / \`render/buffer.ts\` / \`render/fragment.ts\` content stops getting bundled into shared chunks like \`curried-*.js\` at the dist-build stage. Downstream bundlers see the chunks without any debug top-level code at all. | | hello-world raw | hello-world gzip | classic v2-app raw | classic v2-app gzip | | - | - | - | - | - | | before | 133.40 KB | 42.66 KB | 317.74 KB | 98.77 KB | | after | 131.27 KB | 42.06 KB | 309.68 KB | 96.28 KB | Verified: \`pnpm lint\`, \`pnpm type-check:internals\`, both v1/v2-app-template smoke-test \`pnpm test\` pass 1/1, hello-world shrinks across the board. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
1 parent e763868 commit 4b8a9e0

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

rollup.config.mjs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ function sharedESMConfig({ input, debugMacrosMode, includePackageMeta = false })
100100
return {
101101
onLog: handleRollupWarnings,
102102
input,
103+
treeshake: {
104+
moduleSideEffects: moduleHasSideEffects,
105+
},
103106
output: {
104107
format: 'es',
105108
dir: outputDir,
@@ -111,6 +114,26 @@ function sharedESMConfig({ input, debugMacrosMode, includePackageMeta = false })
111114
};
112115
}
113116

117+
// Tell rollup which source files actually have top-level side effects.
118+
// Anything not on this list is treated as side-effect-free, so unused
119+
// imports of it can be elided rather than carried into a downstream
120+
// shared chunk. By default rollup is conservative (`true`) — most
121+
// internal files don't have a `sideEffects: false` package.json visible
122+
// at the right boundary.
123+
function moduleHasSideEffects(id) {
124+
// External (node_modules) — leave default behavior.
125+
if (!id.includes('/packages/')) return true;
126+
// Files under `@glimmer/debug` are pure debug helpers; the package
127+
// itself declares `sideEffects: false`, but that gets lost when files
128+
// are bundled into shared chunks across packages. Force-mark them as
129+
// pure here so unused imports are dropped at the chunk boundary.
130+
if (id.includes('/packages/@glimmer/debug/')) return false;
131+
if (id.includes('/packages/@glimmer/debug-util/')) return false;
132+
if (id.includes('/packages/@glimmer/local-debug-flags/')) return false;
133+
// Default: assume internal files may have side effects.
134+
return true;
135+
}
136+
114137
function glimmerSyntaxESM() {
115138
return {
116139
onLog: handleRollupWarnings,

0 commit comments

Comments
 (0)