Skip to content

fix(concerto-core): remove ESM entrypoint from sideEffects to enable package-level tree shaking - #1263

Draft
mttrbrts wants to merge 2 commits into
mainfrom
fix/tree-shaking-sideeffects
Draft

fix(concerto-core): remove ESM entrypoint from sideEffects to enable package-level tree shaking#1263
mttrbrts wants to merge 2 commits into
mainfrom
fix/tree-shaking-sideeffects

Conversation

@mttrbrts

Copy link
Copy Markdown
Member

Summary

Follow-up fix to PR #1262 (tree-shakeable entrypoints), found during verification of tree-shaking behaviour. Intended to be merged into the Rishabh060105/issue-1261-tree-shaking branch, not directly into main.

  • packages/concerto-core/package.json: removes ./dist/esm/index.mjs from sideEffects; adds ./dist/esm/dayjs-setup.js instead
  • scripts/build-esm.js: adds a second esbuild pass that emits dist/esm/dayjs-setup.js as a separately-referenced file so the sideEffects entry points to a real output file

Why the original sideEffects entry was wrong:
Listing ./dist/esm/index.mjs in sideEffects tells bundlers "this file has side effects — always include it in full." That prevents the package from being excluded when none of its exports are actually imported. The real side effect is dayjs.extend() in dayjs-setup.ts, not the whole index. Pointing sideEffects at the separately-emitted dist/esm/dayjs-setup.js keeps the side effect declared correctly while allowing the main bundle to be skipped at the package boundary.

Verified before/after with Rollup:

Scenario Bundle size
Import only from concerto-util (not concerto-core) 59 KB ✅
Import ModelManager from concerto-core 1.46 MB (expected)

Without this fix, even the "util only" bundle would include the full concerto-core ESM file because it was marked as having side effects.

Remaining known limitation (out of scope for this fix): per-export granular tree shaking within concerto-core does not work because the ESM build is a pre-bundled CJS-in-ESM blob (__commonJS/__esm wrappers). Fixing that requires migrating source files from import X = require() / export = X patterns to native ESM — a larger source refactor for a future PR.

Test plan

  • npm run build:esm in packages/concerto-core produces both dist/esm/index.mjs and dist/esm/dayjs-setup.js
  • A Rollup bundle that only imports from concerto-util does not include concerto-core
  • Existing Playwright browser E2E tests pass (e2e/tests/browser-bundles.spec.ts)
  • DateTimeUtil.setCurrentTime() still works (dayjs plugins correctly extended via inlined setup)

Related Issues

🤖 Generated with Claude Code

Rishabh Jain and others added 2 commits June 14, 2026 11:53
Signed-off-by: Rishabh Jain <rishabhj2005@email.com>
…package-level tree shaking

Listing `./dist/esm/index.mjs` in sideEffects prevented bundlers from
skipping concerto-core entirely when nothing from it is imported.

Instead, emit `dist/esm/dayjs-setup.js` as a separate file and reference
that in sideEffects — keeping the real side effect (dayjs.extend() calls)
declared while allowing the main ESM bundle to be tree-shaken at the
package boundary.

Verified: importing only concerto-util produces a 59 KB bundle;
adding concerto-core jumps to 1.46 MB, confirming the package is
correctly excluded when unused.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Matt Roberts <code@rbrts.uk>
@Rishabh060105

Rishabh060105 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Hi @mttrbrts, I think I would prefer dayjs-setup.mjs since the package does not use type:module.This way we can also reduce ambiguity.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

This PR is stale because it has been open with no activity. Remove the stale label or comment to keep it active. Only items with maintainer engagement are auto-closed.

@github-actions github-actions Bot added the Stale label Jul 3, 2026
@Rishabh060105

Rishabh060105 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@github unstale

@github-actions github-actions Bot removed the Stale label Jul 17, 2026
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

This PR is stale because it has been open with no activity. Remove the stale label or comment to keep it active. Only items with maintainer engagement are auto-closed.

@github-actions github-actions Bot added the Stale label Aug 1, 2026
@Rishabh060105

Copy link
Copy Markdown
Contributor

@github unstale

@github-actions github-actions Bot removed the Stale label Aug 2, 2026
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.

2 participants