Tree-Shaking with Pure Imports
Why Tree-Shaking Matters
Babylon.js is a large framework. @babylonjs/core contains over 2,200 source files covering rendering, physics, animation, XR, particles, materials, loaders, and many other systems. Most applications use only part of this functionality, so bundling the whole package can include code your application never runs.
Tree-shaking lets bundlers such as Webpack, Rollup, Vite, and esbuild figure out which code your application actually uses and remove the rest from the final bundle. This can cut bundle sizes by 50-80% depending on which features you use.
The Challenge: Side Effects
JavaScript modules can have side effects: code that runs automatically when a file is imported, changing things globally. Babylon.js uses side effects for several compatibility and discovery features:
- Class registration, such as
RegisterClass("BABYLON.Camera", Camera), which lets the engine recreate objects by name when loading saved scenes. - Prototype augmentation, such as
Scene.prototype.enablePhysics = function() {...}, which attaches optional methods to existing classes. - Shader registration, which stores GPU shader source code so the engine can compile it later.
- Feature registration, such as making WebXR features available by name.
When a module has side effects, bundlers cannot safely remove it just because your code does not reference one of its exports. This is why @babylonjs/core historically shipped with sideEffects: ["**/*"], telling bundlers that every file might have side effects.
The Pure Barrel
Babylon.js provides an alternative import system where side effects are moved into explicit registration functions. This makes it possible to import from a single barrel while keeping tree-shaking effective.
| Import style | Example | Tree-shakeable | Side effects |
|---|---|---|---|
| Standard top-level barrel | @babylonjs/core | Limited | Automatic |
| ES6 deep imports | @babylonjs/core/Engines/engine.js | Yes | Imported explicitly |
| Pure barrel | @babylonjs/core/pure | Yes | Registered explicitly |
A barrel is a single file that re-exports symbols from many other files, giving you one convenient import path. The pure barrel re-exports the pure implementation modules without running their side effects. Your bundler can analyze which exports you import from the barrel and remove unused code, while features that historically depended on side effects are activated with explicit registration functions.
How It Works
Most files in Babylon.js have no side effects and use their regular file name. The multi-file split only applies to modules that have side effects.
For those modules, the code is split into up to three files:
camera.pure.ts -> Pure implementation and registration functioncamera.types.ts -> Type augmentations only, when neededcamera.ts -> Backward-compatible wrapper that registers side effects.pure.tscontains the implementation. Nothing runs automatically when you import it. It exports aRegisterXxx()function that you call when you need the side effects..types.tscontains TypeScriptdeclare moduleaugmentations for methods added to other classes. It is only needed when a file adds methods or properties to another class..tsre-exports the pure module and calls the registration function to preserve existing import behavior.
If a module has no side effects, it just uses a normal .ts file. No .pure.ts or .types.ts file is needed.
Quick Start
This example imports from the pure barrel and explicitly registers the core engine extensions needed for rendering. The bundler can eliminate everything you do not use.
The example assumes your HTML contains a <canvas id="renderCanvas"></canvas> element.
import { Engine, Scene, FreeCamera, HemisphericLight, CreateSphere, StandardMaterial, Color3, Vector3, RegisterCoreEngineExtensions } from "@babylonjs/core/pure";
RegisterCoreEngineExtensions();
const canvas = document.getElementById("renderCanvas") as HTMLCanvasElement;const engine = new Engine(canvas, true);const scene = new Scene(engine);
const camera = new FreeCamera("camera", new Vector3(0, 5, -10), scene);camera.setTarget(Vector3.Zero());
new HemisphericLight("light", new Vector3(0, 1, 0), scene);
const material = new StandardMaterial("sphereMat", scene);material.diffuseColor = new Color3(0.4, 0.6, 0.9);
const sphere = CreateSphere("sphere", { diameter: 2, segments: 32 }, scene);sphere.material = material;
engine.runRenderLoop(() => scene.render());The pure barrel re-exports every class and function from the package. Your bundler figures out which exports you actually use and removes the rest, giving you the same tree-shaking benefit as individual .pure imports with less import code.
Engine Registration Tiers
Engine extensions such as texture loading, alpha blending, render targets, and uniform buffers are side effects that must be registered when using pure imports. Three tiered helpers are available:
| Helper | What it registers |
|---|---|
RegisterCoreEngineExtensions() | DOM binding, render passes, GPU states, and stencil support |
RegisterStandardEngineExtensions() | Core plus textures, file loading, alpha, render targets, and uniform buffers |
RegisterFullEngineExtensions() | Standard plus cube/raw/dynamic textures, multi-render, multiview, queries, compute, video, debug |
For most applications, RegisterStandardEngineExtensions() is the right choice. Use RegisterFullEngineExtensions() if you need advanced features like compute shaders, cube textures, or multiview rendering.
When to Use Pure Imports
| Scenario | Recommended approach |
|---|---|
| Production app optimizing bundle size | Pure imports and explicit registration |
| Rapid prototyping | Standard imports or the Playground |
| Library or plugin built on Babylon.js | Pure imports, so consumers decide what to register |
| Loading serialized scenes | Pure imports plus registration for serialized types |
| Math-only or utility-only code | Pure deep imports or standalone function imports |
Next Steps
- Using Pure Imports explains pure barrel paths, subdirectory barrels, type augmentations, static function alternatives, and bundler configuration.
- Registering Side Effects explains how to activate optional features when using pure imports.
- Troubleshooting Pure Imports covers the most common runtime and TypeScript errors.
- Adding Tree-Shakeable Features describes the framework contribution pattern for pure modules.
Further reading
Using Pure Imports
Import Babylon.js through pure paths and the pure barrel without losing tree-shaking.

Registering Side Effects
Activate Babylon.js side-effect features explicitly when using pure imports.

Troubleshooting Pure Imports
Diagnose common runtime and TypeScript issues when using Babylon.js pure imports.

Coming next
Using Pure Imports
Import Babylon.js through pure paths and the pure barrel without losing tree-shaking.

Registering Side Effects
Activate Babylon.js side-effect features explicitly when using pure imports.

Troubleshooting Pure Imports
Diagnose common runtime and TypeScript issues when using Babylon.js pure imports.

Adding Tree-Shakeable Features
Follow the Babylon.js pure-module pattern when contributing new tree-shakeable code.
