Back to Babylon Js

Tree-Shaking Scripts

scripts/treeshaking/README.md

9.8.014.5 KB
Original Source

Tree-Shaking Scripts

This folder contains the supported maintenance scripts for the @babylonjs/core tree-shaking split. These scripts keep the pure import surface, side-effect metadata, generated barrels, generated warning stubs, and bundle smoke tests in sync.

Most contributors should use the npm run ... commands from the repository root instead of invoking the .mjs files directly. Direct script invocation is useful when debugging a single tool, running with --verbose, or using --dry-run before writing generated output.

The one-off migration helpers used to create the split live in migration/. They are kept for reference and follow-up migration work, but they are not part of the normal contributor workflow.

Quick Reference

CommandWrites filesPurpose
npm run check:treeshaking-allNoRuns the full supported verification set: generated invariants, side-effects sync, and bundle smoke tests.
npm run check:treeshakingNoRuns manifest drift, pure barrel, and side-effect stub checks.
npm run test:treeshakingNoBundles representative entry points with Rollup and Webpack and checks expected bundle sizes.
npm run update:manifestYesRegenerates side-effects-manifest.json from source analysis.
npm run generate:pure-barrelsYesRegenerates generated pure.ts barrels under packages/dev/core/src.
npm run generate:side-effect-stubsYesRegenerates generated missing-side-effect warning stubs in target class files.
npm run check:side-effects-syncNoChecks that the public package sideEffects field matches the manifest.
npm run inject:pure-annotationsYesAdds missing /*#__PURE__*/ annotations to compiled .pure.js output.

Run this after changing files that affect tree-shaking behavior:

sh
npm run check:treeshaking-all

Run this when source changes intentionally alter generated tree-shaking metadata:

sh
npm run update:manifest
npm run generate:pure-barrels
npm run generate:side-effect-stubs
npm run check:treeshaking-all

How The Scripts Fit Together

Tree-shaking support is maintained through three related data sets:

  1. scripts/treeshaking/side-effects-manifest.json records which @babylonjs/core source files have module-level side effects.
  2. Generated pure.ts barrels expose side-effect-free import paths by re-exporting .pure.ts files, side-effect-free plain .ts files, and child pure.ts barrels.
  3. Generated side-effect stubs add helpful missing-import warnings for methods and properties declared through .types.ts module augmentations.

The manifest is the input for both pure barrel generation and the public package sideEffects field. If a source file gains or loses module-level side effects, regenerate the manifest first, then regenerate or check the consumers of that manifest.

Package Wiring

The supported scripts are wired into the repository in a few places:

LocationWiring
Root lint:check and lint:check-ciRun ESLint, then check:treeshaking, then check:side-effects-sync.
Root build:es6Runs the normal ES6 build and then check:treeshaking-all.
Root check:treeshaking-allRuns check:treeshaking, check:side-effects-sync, and test:treeshaking.
packages/dev/core precompileRegenerates the side-effects manifest, syncs package sideEffects, and regenerates pure barrels before compiling.
packages/dev/core compile:sourceRuns TypeScript and then injectPureAnnotations.mjs against compiled output.
packages/public/@babylonjs/core postcompileRuns injectPureAnnotations.mjs against the public package output.

Supported Scripts

auditSideEffects.mjs

Scans packages/dev/core/src and reports files with module-level side effects. The scanner recognizes patterns such as RegisterClass(...), prototype assignments, shader store registration, node constructor registration, bare top-level calls, static class property assignments, and declare module augmentations.

Common commands:

sh
npm run audit:side-effects
npm run update:manifest
node scripts/treeshaking/auditSideEffects.mjs --json
node scripts/treeshaking/auditSideEffects.mjs --out scripts/treeshaking/side-effects-manifest.json

Use npm run update:manifest when intentional source changes alter which files are side-effectful. The generated manifest should be committed when it changes.

checkManifestDrift.mjs

Regenerates the side-effects manifest into a temporary file and compares it to the committed side-effects-manifest.json. It exits nonzero when the committed manifest is stale.

Common command:

sh
npm run check:manifest-drift

If this check fails, run npm run update:manifest, review the manifest diff, and then run npm run check:treeshaking-all.

syncSideEffects.mjs

Reads side-effects-manifest.json and synchronizes the public @babylonjs/core package sideEffects array. This tells bundlers which compiled package files must be retained for module-level side effects.

Common commands:

sh
node scripts/treeshaking/syncSideEffects.mjs
npm run check:side-effects-sync
node scripts/treeshaking/syncSideEffects.mjs --dry-run --verbose

Normal mode writes packages/public/@babylonjs/core/package.json. --check mode validates the package file without writing.

generatePureBarrels.mjs

Generates pure.ts barrels beside index.ts files under packages/dev/core/src. Each generated barrel starts with the standard generated header and re-exports only side-effect-free modules.

Inputs include:

  • Existing .pure.ts files.
  • The side-effects manifest.
  • Existing index.ts export structure.
  • Child directory pure.ts barrels.

Common commands:

sh
npm run generate:pure-barrels
npm run check:pure-barrels
node scripts/treeshaking/generatePureBarrels.mjs --dry-run --verbose

Normal mode writes generated pure.ts barrels and formats them. --check mode compares on-disk generated barrels with expected content and also reports stale generated barrels that are no longer expected.

generateSideEffectStubs.mjs

Generates missing-side-effect warning stubs for public methods and properties declared by .types.ts module augmentations. These stubs make an unregistered augmented API fail with a helpful warning instead of a plain TypeError.

The script:

  • Scans every .types.ts file under packages/dev/core/src.
  • Parses declare module blocks and their exported interfaces.
  • Resolves each augmentation target to a .pure.ts or .ts file.
  • Injects generated regions between GENERATED_SIDE_EFFECT_STUBS markers.
  • Prunes child-class stubs when an ancestor prototype already provides the same warning stub.

Common commands:

sh
npm run generate:side-effect-stubs
node scripts/treeshaking/generateSideEffectStubs.mjs --check
node scripts/treeshaking/generateSideEffectStubs.mjs --dry-run --verbose

Normal mode writes generated regions and removes stale generated regions. --check mode validates existing regions without writing and reports stale generated regions that should be removed.

verifyTreeShaking.mjs

Runs the core generated-invariant checks in sequence:

  1. Manifest drift.
  2. Pure barrels.
  3. Side-effect stubs.

Common command:

sh
npm run check:treeshaking

This is the check used by root lint:check and lint:check-ci. It does not run the bundle smoke tests or the public package sideEffects sync check; use npm run check:treeshaking-all for the larger verification set.

bundleSmokeTest.mjs

Builds representative entry points with Rollup and Webpack and checks that bundle sizes stay within expected bounds. The tests cover cases such as pure utility imports, pure package barrels, side-effectful wrapper imports, pure registration imports, and explicit registration calls.

Common command:

sh
npm run test:treeshaking

Prerequisites:

  • packages/dev/core/dist must exist.
  • Rollup and Webpack must be available from the repository dependencies.

This script writes temporary files under scripts/treeshaking/.tmp while running and removes them afterward.

injectPureAnnotations.mjs

Post-processes compiled .pure.js files and injects missing /*#__PURE__*/ annotations for top-level call expressions where TypeScript dropped the annotation during emit. This is especially important for static class field initializers that compile into top-level assignments.

Common commands:

sh
npm run inject:pure-annotations
node scripts/treeshaking/injectPureAnnotations.mjs --dry-run --verbose

The script intentionally does not annotate decorator helper calls such as __decorate(...), because those calls mutate prototypes and must not be removed as pure work.

splitRegisterClass.mjs

Transforms files whose only module-level side effect is RegisterClass(...) into the tree-shaking split shape:

  • file.pure.ts contains the implementation.
  • file.ts is the compatibility wrapper that re-exports the pure implementation and performs RegisterClass(...).

Common commands:

sh
npm run split:register-class
node scripts/treeshaking/splitRegisterClass.mjs --dry-run --file Maths/math.color.ts --verbose

This is a source-modifying maintenance script. Use --dry-run first, review the diff carefully, and run the generated checks afterward.

catalogStaticHelpers.mjs

Reports static helper coverage for selected high-priority classes by comparing class static methods and properties against exported free functions in related *.functions.ts files.

Common commands:

sh
npm run catalog:static-helpers
node scripts/treeshaking/catalogStaticHelpers.mjs --verbose

This is an analysis/reporting tool. It does not write files and is not part of the normal lint or build verification path.

Generated Files And Artifacts

ArtifactOwner scriptCommit it?
scripts/treeshaking/side-effects-manifest.jsonauditSideEffects.mjs --outYes, when source side-effect classification intentionally changes.
packages/public/@babylonjs/core/package.json sideEffectssyncSideEffects.mjsYes, when the synced sideEffects array changes.
packages/dev/core/src/**/pure.ts generated barrelsgeneratePureBarrels.mjsYes, when generated barrel content changes.
GENERATED_SIDE_EFFECT_STUBS regionsgenerateSideEffectStubs.mjsYes, when generated stubs change.
packages/dev/core/dist/**/*.pure.js annotationsinjectPureAnnotations.mjsNo for normal source PRs, because dist is build output.
scripts/treeshaking/.tmpbundleSmokeTest.mjsNo. Temporary test workspace only.

Common Workflows

After Adding Or Removing A .pure.ts File

sh
npm run generate:pure-barrels
npm run check:treeshaking-all

Review and commit any generated pure.ts barrel changes.

After Adding Or Removing A Module-Level Side Effect

sh
npm run update:manifest
node scripts/treeshaking/syncSideEffects.mjs
npm run generate:pure-barrels
npm run check:treeshaking-all

Review and commit manifest, package sideEffects, and generated barrel changes as appropriate.

After Adding A .types.ts Module Augmentation

sh
npm run generate:side-effect-stubs
npm run check:treeshaking-all

Review and commit any generated stub region changes.

Before Opening Or Updating A Tree-Shaking PR

sh
npm run check:treeshaking-all

For broader repository confidence, also run the standard repo checks documented at the root of the project.

Check Modes And Write Modes

Several scripts support both write mode and check mode:

ScriptWrite modeCheck mode
generatePureBarrels.mjsWrites generated pure.ts barrels.--check verifies expected content and stale generated barrels.
generateSideEffectStubs.mjsWrites and removes generated stub regions.--check verifies expected regions and stale generated regions.
syncSideEffects.mjsWrites public package sideEffects.--check verifies the package file is in sync.

Prefer check mode in CI and write mode during local maintenance. When a check fails, run the matching write command, review the diff, and rerun npm run check:treeshaking-all.

Migration Scripts

The scripts in migration/ were created for one-time migration phases while building the tree-shaking split. They may still be useful for investigation or future large migrations, but they are not CI-supported maintenance commands. Do not add new lint, build, or test dependencies on migration scripts without first promoting and documenting the script as supported tooling in this README.