docs/tree-shaking/04-troubleshooting.md
Cause: You're using a feature that needs a registration call, but you haven't called it yet.
Example:
Uncaught StandardMaterial needs to be imported before as it contains a side-effect required by your code.
Fix: Import and call the corresponding registration function:
import { RegisterStandardMaterial } from "@babylonjs/core/pure";
RegisterStandardMaterial();
Common triggers and their registrations:
| Error Message | Registration Needed |
|---|---|
StandardMaterial needs to be imported... | RegisterStandardMaterial() |
ImageProcessingConfiguration needs to be imported... | RegisterImageProcessingConfiguration() |
ColorCurves needs to be imported... | RegisterColorCurves() |
Texture needs to be imported... | RegisterTexture() |
FresnelParameters needs to be imported... | RegisterFresnelParameters() |
Ray needs to be imported... | RegisterRay() |
CubeTexture needs to be imported... | RegisterCubeTexture() |
InstancedMesh needs to be imported... | RegisterInstancedMesh() |
Cause: The physics component hasn't been registered. The enablePhysics method only becomes available after registration.
Fix:
import { RegisterJoinedPhysicsEngineComponent } from "@babylonjs/core/pure";
import "@babylonjs/core/Physics/joinedPhysicsEngineComponent.types";
RegisterJoinedPhysicsEngineComponent();
Cause: Engine extensions haven't been registered. When using pure imports, the engine starts with minimal functionality — texture loading, alpha blending, render targets, etc. are all optional extensions.
Fix: Register engine extensions using one of the tiered helpers:
import { RegisterStandardEngineExtensions } from "@babylonjs/core/pure";
RegisterStandardEngineExtensions(); // Covers most use cases
For advanced features (compute shaders, cube textures, multiview), use RegisterFullEngineExtensions() instead. See Engine Registration Tiers for details.
Cause: Ray/picking functionality hasn't been registered.
Fix:
import { RegisterRay } from "@babylonjs/core/pure";
RegisterRay();
Cause: The type augmentation file hasn't been imported. The enablePhysics method is added at runtime by the registration function, but TypeScript needs a separate .types import to know it exists.
Fix: Import the .types file:
import "@babylonjs/core/Physics/joinedPhysicsEngineComponent.types";
Cause: Features have dependencies. For example, ImageProcessingConfiguration depends on ColorCurves, which depends on Texture. Each missing dependency throws a separate error.
Solutions:
Use CheckMissingImports to discover all missing registrations at once:
import { CheckMissingImports } from "@babylonjs/core/Misc/checkMissingImports";
CheckMissingImports(); // Logs ALL missing modules
Common dependency chains are handled automatically. For example, RegisterImageProcessingConfiguration() automatically calls RegisterColorCurves().
For scene loading, register all likely-needed parsers upfront:
import { RegisterStandardMaterial, RegisterPBRMaterial, RegisterImageProcessingConfiguration, RegisterTexture, RegisterFresnelParameters } from "@babylonjs/core/pure";
RegisterStandardMaterial();
RegisterPBRMaterial();
RegisterImageProcessingConfiguration();
RegisterTexture();
RegisterFresnelParameters();
Cause: The material's class wasn't registered, so the scene loader can't recreate it from saved data.
Fix: Register the specific material type:
import { RegisterPBRMaterial } from "@babylonjs/core/pure";
RegisterPBRMaterial();
Cause: A shader include hasn't been registered into the shader store. This happens when you use a material or effect that needs specific shader includes.
Fix: Import the material module (which registers its shaders):
import { RegisterStandardMaterial } from "@babylonjs/core/pure";
RegisterStandardMaterial();
Or for custom shaders, import the includes directly:
import "@babylonjs/core/Shaders/ShadersInclude/helperFunctions";
The primary diagnostic tool for pure imports. Call it at startup to see all stubs that haven't been registered:
import { CheckMissingImports } from "@babylonjs/core/Misc/checkMissingImports";
// After all your imports, before creating the scene:
const missing = CheckMissingImports();
if (missing.length > 0) {
console.log("You may need to register:", missing);
}
What it checks:
Important: Not all reported modules are required. The report lists what's available but unregistered. Only import what your app actually uses.
When using pure imports, methods that would normally be added by side effects are replaced with lightweight placeholders (stubs). These stubs:
undefined (a falsy value in JavaScript) — so feature-detection code like if (scene.getPhysicsEngine()) works correctlyTypeError if you try to use the return value as an objectThis means code like if (scene.getPhysicsEngine()) { ... } works correctly without the physics registration — it simply evaluates to false.
To debug a pure-import scene and see which missing side-effect registrations are actually being called, enable runtime stub warnings during development:
import { SetMissingSideEffectWarningsEnabled } from "@babylonjs/core/Misc/devTools";
SetMissingSideEffectWarningsEnabled(true);
With this enabled, each missing side-effect stub logs at most once:
[Babylon.js] Scene.getPhysicsEngine() requires a side-effect import. See: https://doc.babylonjs.com/setup/treeshaking
If your code intentionally probes optional augmented APIs, suppress warnings around that synchronous probe:
import { SuppressMissingSideEffectWarnings } from "@babylonjs/core/Misc/devTools";
SuppressMissingSideEffectWarnings(() => {
scene.getPhysicsEngine?.();
});
Use runtime warnings as a development diagnostic. For a broad startup report of all known unregistered stubs, use CheckMissingImports() instead.
Register side effects before you use them. The best pattern is to group all registrations at the top of your application entry point:
// app.ts — entry point
import { RegisterStandardMaterial, RegisterRay, RegisterJoinedPhysicsEngineComponent } from "@babylonjs/core/pure";
// Register everything at startup
RegisterStandardMaterial();
RegisterRay();
RegisterJoinedPhysicsEngineComponent();
// Then create your scene...
Registration functions add very little overhead — they're typically 5–20 lines that set up methods on classes. The real bundle savings come from not importing the modules you don't need:
| Approach | Approximate Bundle Size |
|---|---|
@babylonjs/core (everything) | ~6+ MB minified |
@babylonjs/core/pure (typical app) | ~1.5–3 MB minified |
| Minimal scene (pure, few registrations) | ~1–1.5 MB minified |
When converting an existing project from legacy to pure imports:
.pure paths or the pure barrelimport "@babylonjs/core/..." that don't import any namesimport { RegisterXxx } from "@babylonjs/core/pure" + RegisterXxx().types imports for any features that add methods to existing classesCheckMissingImports() to catch anything you missedCheckMissingImports from production builds