API

Babylon.js ES6 support with Tree Shaking

Introduction

The NPM package manager is one of the best ways to define and organize your project's dependencies. Compared to traditional JavaScript development (including a script in a 'script' HTML Tag), using npm packages allows you to use tools like Webpack or Browserify to pack your project and (continuously) deliver it.

We now officially support our npm ES6 packages and will continue updating the npm repository with new versions as they are developed.

Please note that by using ES6 packages, you will need to rely on extra tooling to bundle and test your library but on the bright side you will be able to tree shake your application and reduce its final size.

All the Babylon.js ES6 packages are available within the npm scope @babylonjs.

Available packages

We offer Babylon.js core and its modules as npm packages. The following are available:

Basic Example

A boilerplate project with a few examples on how to use the ES6 modules can be found here - Babylon.js, Webpack and ES6 modules on GitHub. It is a project skeleton, based on TypeScript, Webpack and our ES6 modules. The different scenes (Asset loading, physics, simple scene) to show the different aspects of module-loading and Babylon.js.

Basic usage

As the ES6 version is composed of many separate files the usual way to consume such packages is through Webpack or other bundlers. The following examples will be done with Webpack but you could rely on any of the tools you are familiar with.

Application Creation Summary

  1. Create new folder MyAwesomeApp
  2. Open GitBash (or similar) for MyAwesomeApp
  3. Run npm init
  4. Run npm install webpack webpack-cli webpack-dev-server --save-dev
  5. Run npm install @babylonjs/core @babylonjs/materials
  6. Create Folder public in MyAwesomeApp and create index.html file in public as described in First App Section below
  7. Create Folder src in MyAwesomeApp
  8. Create index.js file in src as described in First App Section below
  9. Run npx webpack serve to check result in http://localhost:8080/
  10. Run npx webpack to create dist folder

Read all the following sections for full description.

Using Webpack

First create a new folder where you will develop your app: mkdir MyAwesomeApp .

Then navigate to the folder cd MyAwesomeApp and initialize npm with the command npm init. Simply fill out the requested questions or leave the defaults if you prefer.

You can then install Webpack like this: `npm install webpack webpack-cli webpack-dev-server --save-dev`. This will also install a local dev server, which is pretty handy for local development.

Following the default Webpack convention, you do not even need a configuration file.

Installing Babylon.js

To install the latest Babylon.js ES6 version, use:

npm install @babylonjs/core

This will install Babylon.js's JavaScript files and will also include a TypeScript declaration file.

To include the whole of Babylon in a javascript or typescript file, use:

import * as BABYLON from "@babylonjs/core/Legacy/legacy.js";

This will work exactly like the non-ES6 version and the entire library will be included as a dependency.

You can also load specific classes to help with your code:

import { Engine, Scene } from "@babylonjs/core";

NOTE: Some of the modules work through side effects, so you might need to `import "@babylonjs/core/Meshes/meshBuilder.js"` for side effects only in order to rely on any of the Mesh creation static methods like `MeshBuilder.CreateBox` for instance. This was the best way to deliver our ES6 version without breaking backward compatibility of the bundled version.

Installing other Babylon modules

After including `@babylonjs/core` you can add Babylon's extra modules using npm as follows:

npm install --save-dev @babylonjs/materials [other packages]

As with Babylon.js, this will install the JavaScript files and a declaration file.

To import the dependencies, you simply need to import the library (without giving it a namespace):

import {
GridMaterial
} from '@babylonjs/materials';
let gridMaterial = new GridMaterial(.....)

Creating our first JS App

Now we have all the dependencies created, create an index.html file in the public folder and fill it with the following code:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Local Development</title>
<script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
<style>
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
#renderCanvas {
width: 100%;
height: 100%;
display: block;
font-size: 0;
}
</style>
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas>
<script src="main.js"></script>
</body>
</html>

This will only have a fullscreen canvas as well as a reference to our application file (by default webpack output during development is "main.js");

Once done you can create a src folder containing an index.js file with the following content:

import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera.js";
import { Engine } from "@babylonjs/core/Engines/engine.js";
import { HemisphericLight } from "@babylonjs/core/Lights/hemisphericLight.js";
import { Vector3 } from "@babylonjs/core/Maths/math.vector.js";
import { CreateGround } from "@babylonjs/core/Meshes/Builders/groundBuilder.js";
import { CreateSphere } from "@babylonjs/core/Meshes/Builders/sphereBuilder.js";
import { Scene } from "@babylonjs/core/scene.js";
import { GridMaterial } from "@babylonjs/materials/grid/gridMaterial.js";
// Get the canvas element from the DOM.
const canvas = document.getElementById("renderCanvas");
// Associate a Babylon Engine to it.
const engine = new Engine(canvas);
// Create our first scene.
const scene = new Scene(engine);
// This creates and positions a free camera (non-mesh)
const camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene);
// This targets the camera to scene origin
camera.setTarget(Vector3.Zero());
// This attaches the camera to the canvas
camera.attachControl(canvas, true);
// This creates a light, aiming 0,1,0 - to the sky (non-mesh)
const light = new HemisphericLight("light1", new Vector3(0, 1, 0), scene);
// Default intensity is 1. Let's dim the light a small amount
light.intensity = 0.7;
// Create a grid material
const material = new GridMaterial("grid", scene);
// Our built-in 'sphere' shape.
const sphere = CreateSphere("sphere1", { segments: 16, diameter: 2 }, scene);
// Move the sphere upward 1/2 its height
sphere.position.y = 2;
// Affect a material
sphere.material = material;
// Our built-in 'ground' shape.
const ground = CreateGround("ground1", { width: 6, height: 6, subdivisions: 2 }, scene);
// Affect a material
ground.material = material;
// Render every frame
engine.runRenderLoop(() => {
scene.render();
});

Finally, you can run the local dev environment with the command npx webpack serve.

Open the browser and navigate to the URL http://localhost:8080/. You should see a sphere and a plane using the Grid Material.

To create the distribution folder dist use the command npx webpack

You may have noticed that we did our imports from files instead of the base modules. This is to ensure we get the full benefit of Tree Shaking. For more information, see the Side Effects section below.

TypeScript

Switching the project to TypeScript is pretty straightforward. First, in the MyAwesomeApp folder from the previous example, we need to install TypeScript and one of the modules that allows its use in Webpack: npm install typescript ts-loader --save-dev

Once that is done, we can replace our previous index.js with its TypeScript equivalent, index.ts:

import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera.js";
import { Engine } from "@babylonjs/core/Engines/engine.js";
import { HemisphericLight } from "@babylonjs/core/Lights/hemisphericLight.js";
import { Vector3 } from "@babylonjs/core/Maths/math.vector.js";
import { CreateGround } from "@babylonjs/core/Meshes/Builders/groundBuilder.js";
import { CreateSphere } from "@babylonjs/core/Meshes/Builders/sphereBuilder.js";
import { Scene } from "@babylonjs/core/scene.js";
import { GridMaterial } from "@babylonjs/materials/grid/gridMaterial.js";
// Get the canvas element from the DOM.
const canvas = document.getElementById("renderCanvas") as HTMLCanvasElement;
// Associate a Babylon Engine to it.
const engine = new Engine(canvas);
// Create our first scene.
const scene = new Scene(engine);
// This creates and positions a free camera (non-mesh)
const camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene);
// This targets the camera to scene origin
camera.setTarget(Vector3.Zero());
// This attaches the camera to the canvas
camera.attachControl(canvas, true);
// This creates a light, aiming 0,1,0 - to the sky (non-mesh)
const light = new HemisphericLight("light1", new Vector3(0, 1, 0), scene);
// Default intensity is 1. Let's dim the light a small amount
light.intensity = 0.7;
// Create a grid material
const material = new GridMaterial("grid", scene);
// Our built-in 'sphere' shape.
const sphere = CreateSphere('sphere1', { segments: 16, diameter: 2 }, scene);
// Move the sphere upward 1/2 its height
sphere.position.y = 2;
// Affect a material
sphere.material = material;
// Our built-in 'ground' shape.
const ground = CreateGround('ground1', { width: 6, height: 6, subdivisions: 2 }, scene);
// Affect a material
ground.material = material;
// Render every frame
engine.runRenderLoop(() => {
scene.render();
});

The only change is the addition of as HTMLCanvasElement on the canvas element.

With that done, we need to configure Webpack to allow the use of TypeScript. Add a webpack.config.js at the root of your project containing the following:

module.exports = {
resolve: {
extensions: [".ts", ".js"],
},
module: {
rules: [
{
test: /\.tsx?$/,
loader: "ts-loader",
},
],
},
};

We also need to configure TypeScript in the application folder. The simplest is to add a tsconfig.json file at the root of the project containing:

{
"compilerOptions": {
"module": "esNext",
"target": "es5",
"moduleResolution": "node",
}
}

This will ensure our Babylon.js module can be loaded and used in your application.

It is time to run again with the command npx webpack serve and open your browser at http://localhost:8080/. You should see a sphere and a plane using the Grid Material exactly as in JavaScript. You are now fully ready to use the Babylon.js ES6 packages in TypeScript.

As in the Creating our first js APP section above, we did our imports from files instead of the base modules. This is to ensure we get the full benefit of Tree Shaking. For more information, see the Side Effects section below.

Tree Shaking

From the beginning you could wonder why using these ES6 packages vs the default bundled ones. Besides being more "modern," which is not a valuable enough argument on its own to make the switch, you can now fully benefit from tree shaking.

This means the previous example now requires about 700Kb versus 2.3Mb before.

Please note we are continuing to improve our min package size by decoupling a bit more our packages so if you spot any unnecessary dependency, please, do not hesitate to create an issue on GitHub.

As you will see in the next paragraph, you also need to target individual files to fully benefit from tree shaking in your app.

Babylon.js also provides a pure import system that lets you import from a single barrel while preserving tree-shaking. See Tree-Shaking with Pure Imports for the pure barrel workflow.

Side Effects

Due to our attachment to backward compatibility, we had to make a hard choice between the APIs and the side effects. Actually whilst not working with modules, it is easy to not worry about side effects and we relied on this pattern a lot to create a friendlier API surface. For instance, you can directly use the Mesh class to create basic shapes like cubes, spheres and so on. Despite being convenient, this means that the full MeshBuilder constructs are then a dependency of Mesh. But what if you are not using any of them? Why should they be part of the final package?

Easy call, we could move those functions elsewhere and we did exactly this by creating smaller builder modules dedicated to construct only one type of shapes. But now quid of back compat? Yup, it is lost so to ensure you could use the same code in both UMD bundle and ES6, when the builder files are being parsed, they are swapping the MeshBuilder methods. This implies a side effect A module executing code whilst being parsed. This is the tradeoff we had to make, valuing back compatibility and API consistency vs side effect free code.

As a result, it is impossible for Webpack and the other bundlers to determine if imports are safe to be removed when not used so if you import directly from index, all the imports will be followed and included in your packages.

The solution, even if a bit annoying, is simple: you need to import manually only from the modules you need. This will force you to target your imports on the dedicated modules (vs index ones) if you want to fully benefit from tree shaking. The folder structure should be natural enough and in case you are finding some modules in not intuitive locations, do not hesitate to file an issue on GitHub and we will be more than happy to document it here.

FAQ

How do I efficiently use the Mesh.Create... methods?

The simplest is to load only the builder corresponding to your construction method. If you wish to use the CreateBox method, you can simply import "@babylonjs/core/Meshes/Builders/boxBuilder.js"; to ensure that the dependant modules have been loaded.Except if you are relying on all the MeshBuilder methods, we would recommend to not use it directly but favor the smaller builders.

Why using the default material is not working? By default, any mesh in a scene are using the scene defaultMaterial. With tree shaking you might not need this material so we do not force it as a dependency in the code. That said, would you need to use it, you can simply `import "@babylonjs/core/Materials/standardMaterial.js";` to ensure that the default material would be operational.

How does deserialization work?

When you deserialize a Babylon.js object like a Material or Light, it is impossible for the framework to know beforehand what kind of entity is enclosed in your file. For instance, are you relying on Standard vs PBRMaterial. We again rely on side effect here and the deserialization will only be able to load the kind of entity you have imported in your app. This means if you know you will need to deserialize a PBRMaterial, you can import "@babylonjs/core/Materials/PBR/pbrMaterial.js"; beforehand.

How do I know if I am importing a folder or a file?

By convention and to simplify the discovery, all folders start with an upper-case character, whereas files start with a lower-case one.

How to find what module contains the entity I am trying to import?

This is actually a pretty good question. It should be intuitive enough and if not, do not hesitate to ping us so we can add it to the documentation.

The intellisense does not propose the method I normally use in the bundled version and an undefined error is raised at runtime?

Your IDE may not be able to discover methods defined by module augmentation. This means that as long as you are not importing the parent modules, the methods will not even be discoverable. This is the case for all our scene components. For enabling physics on the scene you need import "@babylonjs\core\Physics\physicsEngineComponent.js" to populate the scene.enablePhysics function.

Please find below the list of those components for their augmented methods (note that all imports of files must include the extension):

  • scene."animationRelatedMethods" like beginAnimation and so on... " are available in the Animations/animatable.js module.
  • scene."audioRelatedMethods" are available in the Audio/audioSceneComponent.js and Audio/audioEngine.js module.
  • Octree functions can be found in the Culling/Octrees/octreeSceneComponent.js module.
  • Ray and Picking functions can be found in the Culling/ray.js module.
  • Debug Layer functions can be found in the Debug/debugLayer.js module.
  • Occlusion Queries can be found in the Engines/Extensions/engine.query.js module.
  • Transform Feedback can be found in the Engines/Extensions/engine.transformFeedback.js module.
  • Gamepad support can be found in the Gamepad/gamepadSceneComponent.js module.
  • Scene Helpers like createDefaultCamera, createDefaultXXX can be found in the Helpers/sceneHelpers.js module.
  • Mesh Simplification functions can be found in the Meshes/meshSimplicationSceneComponent.js .
  • DDS Loader support can be installed from the Materials/Textures/Loaders/ddsTextureLoader.js and you will also need core/Misc/dds.js module.
  • Env Loader support can be installed from the Materials/Textures/Loaders/envTextureLoader.js .
  • KTX Loader support can be installed from the Materials/Textures/Loaders/ktxTextureLoader.js .
  • TGA Loader support can be installed from the Materials/Textures/Loaders/tgaTextureLoader.js .
  • Particle support can be found in the Particles/particleSystemComponent.js .
  • For GPUParticleSystem, WebGL2 support can be found in Particles/webgl2ParticleSystem.js and WebGPU support in Particles/computeShaderParticleSystem.js
  • Physics Engine support can be found in the Physics/physicsEngineComponent.js .
  • .babylon file support can be found in the Loading/Plugins/babylonFileLoader.js .
  • shadowGenerator support can be found in the Lights/Shadows/shadowGeneratorSceneComponent.js .
  • depthRendering support can be found in the Rendering/depthRendererSceneComponent.js .
  • screenshot support can be found in the Misc/screenshotTools.js .
  • boundingBox support can be found in the Rendering/boundingBoxRenderer.js .
  • Screen surface reflection postprocess (scene.enablePrePassRender) can be found in the Rendering/prePassRendererSceneComponent.js .
  • Decal Map support is enabled by importing Materials/material.decalMap.js. If you only want to enable support at the mesh level and not the material level, use Meshes/abstractMesh.decalMap.js instead. See here for why you want to do this.

Why do I have a TypeError in the console telling me that something is not a function, even though my IDE shows it via intellisense?

Some methods are added via module augmentation. While some IDEs cannot detect these methods at all, others – like VSCode – seem to be able to find them even when they are not actually available. You will need to import the correct module to add that method. If your issue is with a missing scene method, see the previous question.

Why do I have an error in the console inviting me to import some other modules?

This might happen on some modules where we are heavily relying on side effects and where we can automatically detect the absence of the dependency.

Almighty Inspector

Due to the module names changing and other ES6 module differences, the UMD and CDN inspector version is not compatible with ES6. Nevertheless, you can install the ES6 version of the inspector and import it for side effect only in your code. Then the debug layer would work as usual.

First install the inspector package:

npm install --save-dev @babylonjs/inspector

And then in your code:

import "@babylonjs/core/Debug/debugLayer.js"; // Augments the scene with the debug methods
import "@babylonjs/inspector"; // Injects a local ES6 version of the inspector to prevent automatically relying on the non-compatible version
...
scene.debugLayer.show();

Earcut/Oimo/Canon

As we do not want to force our users to include any dependencies by default, we have extended the way users could rely on external dependencies for ES6.

For each of the external dependencies Babylon.js is relying upon, if you are planning on relying on them, you can provide them as global variables in your bundler. For instance if you are willing to use the PolygonMeshBuilder class in your app you can add earcut in Webpack like this:

module.exports = {
context: __dirname,
...
plugins: [
new webpack.ProvidePlugin({
'earcut': 'earcut'
})
]
}

Or if you do not want to use a global var for earcut, you could simply pass the dependency to the PolygonMeshBuilder class like this:

import * as MyEarcut from "earcut";
...
new PolygonMeshBuilder("polytri", corners, scene, MyEarcut);

It would be the same for the physics plugin, where you can either provide the underlying engine as a variable or inject it in the constructor of the Babylon.js respective plugin.

Havok Physics

The recommended physics engine for Babylon.js is Havok. To use Havok with ES6/npm, install it:

npm install @babylonjs/havok

Then in your code:

import HavokPhysics from "@babylonjs/havok";
import { HavokPlugin } from "@babylonjs/core/Physics/v2/Plugins/havokPlugin.js";
const havokInstance = await HavokPhysics();
const havokPlugin = new HavokPlugin(true, havokInstance);
scene.enablePhysics(new Vector3(0, -9.81, 0), havokPlugin);

Loaders

In Babylon.js the loaders you can install from @babylonjs/loaders are actually plugins of the main SceneLoader module. In order to use for instance the obj loader in your app, you simply need to import it for side effects only: import "@babylonjs/loaders/OBJ.js"; . It would be exactly the same for glTF: import "@babylonjs/loaders/glTF.js"; .

KTX2 Decoder packages

The ES6 KTX2 decoder module includes all of the decoders and their corresponding WASM files and wrappers so users can use them locally and deploy them as part of their build. The KTX2 decoder module is available in the npm scope @babylonjs/ktx2decoder.

To use the KTX2 decoder module, install it as follows:

npm install --save-dev @babylonjs/ktx2decoder

Then, you need to decide if you want to use workers or decode the KTX2 files on the main thread. The difference is in the way you will initialize the module.

If you want to use workers, you will need to generate the worker file that will be used to decode the textures and pass a worker pool. The example below uses the MSC decoder, but the same process can be used to initialize any other type of decoder.

First let's create a worker file. We will call it worker.js (note - typescript will work the same):

// worker.js
import * as KTX2Decoder from "@babylonjs/ktx2decoder";
import { workerFunction } from "@babylonjs/core/Misc/khronosTextureContainer2Worker.js";
import mscTranscoderJsModule from "@babylonjs/ktx2decoder/wasm/msc_basis_transcoder.js";
import { MSCTranscoder as jsMSCTranscoder } from "@babylonjs/ktx2decoder/Transcoders/mscTranscoder.js";
// set the globalThis object to make sure the worker can access the global scope
globalThis.KTX2DECODER = KTX2Decoder;
// set the msc decoder module
jsMSCTranscoder.JSModule = mscTranscoderJsModule;
// Call the worker function, imported from the core module
workerFunction(KTX2Decoder);

Then in your main file, you will need to do a few things:

  1. import the wasm as an arraybuffer
  2. Create a worker pool
  3. Initialize the worker pool with the worker file
  4. Pass the workerpool to the KhronosTextureContainer2 module
// mainFile.js
import { Engine } from "@babylonjs/core/Engines/engine.js";
import { Scene } from "@babylonjs/core/scene.js";
import { Texture } from "@babylonjs/core/Materials/Textures/texture.js";
import wasmMSCTranscoder from "@babylonjs/ktx2decoder/wasm/msc_basis_transcoder.wasm"; // make sure the import is an arraybuffer
import { KhronosTextureContainer2 } from "@babylonjs/core/Misc/khronosTextureContainer2.js";
import { AutoReleaseWorkerPool } from "@babylonjs/core/Misc/workerPool.js";
import { initializeWebWorker } from "@babylonjs/core/Misc/khronosTextureContainer2Worker.js";
import "@babylonjs/core/Materials/Textures/Loaders/ktxTextureLoader.js";
export function initScene(element) {
const engine = new Engine(element);
const scene = new Scene(engine);
// Create a worker pool
// This will be used when a new KhronosTextureContainer2 is created
KhronosTextureContainer2.WorkerPool = new AutoReleaseWorkerPool(4, () => {
// Create a new worker using the worker.js file we have already created
const worker = new Worker(new URL("./worker.js", import.meta.url), {
type: "module",
});
// Initialize the worker with the wasm array buffer
return initializeWebWorker(worker, {
// pass all arraybuffers here
wasmMSCTranscoder,
});
});
// decode the texture
const texture = new Texture(
"./2d_etc1s.ktx2",
scene,
false,
true,
Texture.TRILINEAR_SAMPLINGMODE,
() => {
console.log(texture);
},
(message, exception) => {
console.error("Can't fetch texture", message, exception);
},
);
}

How to get the wasms as arraybuffers

When importing the wasm files, you will need to import them as arraybuffers. As this is non-standard, it depends on your bundler and environment.

When using webpack you can use the arraybuffer-loader. The way to do that is documented here - https://www.npmjs.com/package/arraybuffer-loader#for-wasm-file

When using vite you can use vite-plugin-arraybuffer, documented here - https://www.npmjs.com/package/vite-plugin-arraybuffer.

When using node environment, you can just use the fs module to read the file as an arraybuffer.

Providing your own resources for Draco compression and Basis decoder

We provide the Draco compression and Basis decoder as part of the ES6 @babylonjs/core package. As recommended, it is always better to serve those resources from your own server. If you want them to be included as part of your build process, you can do so by providing the resources directly to the modules.

Draco Decoder packages

Just like with the KTX2 decoder, you need to first decide if you use workers or not. For example, in a node environment you will not be able to use workers, but in a web environment it would be recommended to use them.

If using workers, create a worker file:

// worker.js
import { DecoderWorkerFunction } from "@babylonjs/core/Meshes/Compression/dracoCompressionWorker.js";
// will populate globalThis.DracoDecoderModule
import "@babylonjs/core/assets/Draco/draco_decoder_gltf.js";
DecoderWorkerFunction();

And then create a worker pool:

// mainFile.js
// import the wasm as array buffer. see the KTX2 documentation for hints on how to do that
import wasm from "@babylonjs/core/assets/Draco/draco_decoder_gltf.wasm";
import { AutoReleaseWorkerPool } from "@babylonjs/core/Misc/workerPool.js";
import { DracoDecoder } from "@babylonjs/core/Meshes/Compression/dracoDecoder.js";
import { initializeWebWorker } from "@babylonjs/core/Meshes/Compression/dracoCompressionWorker.js";
import { Tools } from "@babylonjs/core/Misc/tools.js";
import { VertexBuffer } from "@babylonjs/core/Meshes/buffer.js";
const workerPool = new AutoReleaseWorkerPool(4, () => {
const worker = new Worker(new URL("./worker.js", import.meta.url), {
type: "module",
});
return initializeWebWorker(worker, wasm);
});
// set the worker pool
DracoDecoder.DefaultConfiguration.workerPool = workerPool;
// if you are creating your own version of the draco decoder class you can pass the worker pool in the constructor instead:
const dracoDecoder = new DracoDecoder({
workerPool,
});

If you are not using workers, you will need to pass the wasm file and its js module directly to the draco decoder configuration:

// import the wasm file as an arraybuffer
import wasm from "@babylonjs/core/assets/Draco/draco_decoder_gltf.wasm";
// import the js module
import "@babylonjs/core/assets/Draco/draco_decoder_gltf.js";
DracoDecoder.DefaultConfiguration.wasmBinary = wasm;
DracoDecoder.DefaultConfiguration.jsModule = globalThis.DracoDecoderModule;

Using Draco in node environment

To use the draco decoder in nodejs to decode your own file:

const BABYLON = require("babylonjs");
const fs = require("fs");
const xhr = require("xhr2");
require("babylonjs-loaders");
// get the resources from the local disk. Note - the resources need to be downloaded manually.
const Draco = require("./assets/draco_decoder_gltf.js");
const wasm = fs.readFileSync(process.cwd() + "/assets/draco_decoder_gltf.wasm");
BABYLON.DracoDecoder.DefaultConfiguration.wasmBinary = wasm;
BABYLON.DracoDecoder.DefaultConfiguration.jsModule = Draco;
globalThis.XMLHttpRequest = xhr.XMLHttpRequest;
let engine = new BABYLON.NullEngine();
// create your scene here
const scene = .....;
BABYLON.ImportMeshAsync("https://awesomeserver.mine.com/my.glb", scene).then(() => {
console.log("draco worked");
}, (e) => {
console.log("oh no! something is off", e);
}
);

Basis Decoder

The basis decoder doesn't use a worker pool, but does have a worker that can be initialized.

To use the basis decoder in your app, you will need to initialize the worker:

// worker.js
import { workerFunction } from "@babylonjs/core/Misc/basisWorker.js";
import "@babylonjs/core/assets/Basis/basis_transcoder.js";
workerFunction();

Now initialize the webworker on the main thread, and set this worker for basis decoding:

// mainFile.js
import wasm from "@babylonjs/core/assets/Basis/basis_transcoder.wasm";
import { initializeWebWorker } from "@babylonjs/core/Misc/basisWorker.js";
import { SetBasisTranscoderWorker } from "@babylonjs/core/Misc/basis.js";
const worker = new Worker(new URL("./worker.js", import.meta.url), {
type: "module",
});
initializeWebWorker(worker, wasm);
SetBasisTranscoderWorker(worker);

Avoiding side-effects

Starting with Babylon.js v7.23, we are introducing a new way for ES6 users to import optional features without side effects. Depending on how the internal engine works, we have aimed to reduce the number of functions that need to be added at the prototype level. Instead, when possible, we are offering more 'pick and choose' public functions.

For the newer pure-barrel registration model, see Tree-Shaking with Pure Imports and Registering Side Effects.

Animations

  • File to import: "core/Animations/animatable.core" (instead of "core/Animations/animatable" which has side-effects)
  • Function to import and execute to initialize the module: AddAnimationExtensions(sceneClass, boneClass)
  • Calling AddAnimationExtensions will populate the following prototype functions:
    • Bone.prototype.copyAnimationRange
    • Scene.prototype.beginAnimation
    • Scene.prototype.beginDirectAnimation
    • Scene.prototype.beginDirectHierarchyAnimation
    • Scene.prototype.beginWeightedAnimation
    • Scene.prototype.beginHierarchyAnimation
    • Scene.prototype.getAllAnimatablesByTarget
    • Scene.prototype.getAnimatableByTarget
    • Scene.prototype.sortActiveAnimatables
    • Scene.prototype.stopAllAnimations

Ray

  • File to import: "core/Culling/ray.core" (instead of "core/Culling/ray" which has side-effects)
  • Function to import and execute to initialize the module: AddRayExtensions(sceneClass, cameraClass)
  • Calling AddRayExtensions will populate the following prototype functions:
    • Camera.prototype.getForwardRay
    • Camera.prototype.getForwardRayToRef
    • Scene.prototype.createPickingRay
  • The following functions will be available:
    • CreatePickingRay
    • CreatePickingRayToRef
    • CreatePickingRayInCameraSpace
    • CreatePickingRayInCameraSpaceToRef
    • Pick
    • PickWithRay
    • PickWithBoundingInfo
    • MultiPick
    • MultiPickWithRay

Further reading

Framework Versions
Learn about the different versions of Babylon.js.
Framework Versions
NPM Support
Learn about Babylon.js's use of the NPM Package Manager.
NPM Support
Tree-Shaking with Pure Imports
Use the Babylon.js pure barrel to keep a single import surface while preserving tree-shaking.
Tree-Shaking with Pure Imports

    Coming next

    Tree-Shaking with Pure Imports
    Use the Babylon.js pure barrel to keep a single import surface while preserving tree-shaking.
    Tree-Shaking with Pure Imports