Weird issue using Vite

I’m totally new to Vite so maybe it could be just a newbie/stupid issue.

I’ve imported it

import * as BABYLON from ‘@babylonjs/core’;
import ‘@babylonjs/materials’;

But after that, I get this error:

BABYLON.Quaternion.Identity is not a constructor

Any idea about that? Thank you!

I believe you need to do it like it is described at npm documentation

npm install @babylonjs/core --save

This will allow you to import BabylonJS entirely using:

import * as BABYLON from '@babylonjs/core/Legacy/legacy';

or individual classes to benefit from enhanced tree shaking using :

import { Scene } from '@babylonjs/core/scene';
import { Engine } from '@babylonjs/core/Engines/engine'

If you are using the ES Modules, you really should try to import individual classes so you get tree shaking. This will likely resolve your issue as there is probably something you are importing that you don’t need that needs a different import; I suspect it is the materials import. It will also dramatically reduce the size of your js file. Also, if you are building a lib and you plan to mark babylon as external in optimizeDependencies, be advised that importing the entire module as you have done with materials will cause vite to bundle the entire module even if you mark it as external.

2 Likes

Notice that the initializer problem has nothing to do, with importing them individually, it happens too, my solution maybe is not the most elegant one but it works:

rotationQuaternion = new Quaternion(0,0,0,1);

The weird thing is that BABYLON.Quaternion.Identity doesn’t work but the rest of the code (long one) does.

Btw I’ve made:

import {
Engine,
Scene,
ArcRotateCamera,
TransformNode,
CubeTexture,
MeshBuilder,
PBRMaterial,
Vector3,
Quaternion,
SmartArray,
WebXRSessionManager,
WebXRBackgroundRemover,
WebXRFeaturesManager,
WebXRFeatureName,
Mesh,
VideoTexture,
ShadowGenerator,
VertexData,
Color3,
Texture
} from ‘@babylonjs/core’;
import {ShadowOnlyMaterial} from ‘@babylonjs/materials’;

But it doesn’t seem to save space compared to

import * as BABYLON from ‘@babylonjs/core’;
import * as BABYLONM from ‘@babylonjs/materials’;

I’m guessing you’re using

let q = new Quaternion.Identity()

You should actually use

let q = Quaternion.Identity()
2 Likes

I don’t know if it makes a difference, but my imports look like

import { Scene } from '@babylonjs/core/scene';
import { Matrix, Vector3 } from '@babylonjs/core/Maths/math';
import { Viewport } from '@babylonjs/core/Maths/math.viewport';
import { TransformNode } from '@babylonjs/core/Meshes/transformNode';

and I have seen significant size reduction.

1 Like

I would bet on @qq2315137135 suggestion :slight_smile:

BABYLON.Quaternion.Identity is a function, you either

cont toto = new BABYLON.Quaternion(...);

or

cont toto = BABYLON.Quaternion.Identity(); // without new cause not a constructor.
1 Like

It seems that I should specifically import them one by one and the size is heavily reduced.

Unfortunately even after importing cube texture with

import { CubeTexture } from ‘@babylonjs/core/Materials/Textures/cubeTexture’;

after calling it as

let lighting = CubeTexture.CreateFromPrefilteredData(“https://assets.babylonjs.com/environments/studio.env”, scene);

I get this error

fileTools.ts:132 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘replace’)
at _CleanUrl (fileTools.ts:132:15)
at LoadImage (fileTools.ts:192:15)
at ThinEngine._partialLoadImg (engine.cubeTexture.ts:303:5)
at ThinEngine._cascadeLoadImgs (engine.cubeTexture.ts:264:14)
at ThinEngine.createCubeTextureBase (engine.cubeTexture.ts:428:14)
at ThinEngine.createCubeTexture (engine.cubeTexture.ts:464:17)
at _CubeTexture._loadTexture (cubeTexture.ts:408:52)
at _CubeTexture.updateURL (cubeTexture.ts:301:18)
at new _CubeTexture (cubeTexture.ts:218:14)
at _CubeTexture.CreateFromPrefilteredData (cubeTexture.ts:151:24)

Hi! Can you try to add

import "@babylonjs/core/Materials/Textures/Loaders/envTextureLoader";

and see if this resolves the issue?

I have a branch derived from Raanan’s webpack model that uses vite, and I’m able to load a CubeTexture this way: babylonjs-webpack-es6/src/scenes/loadModelAndEnv.ts at vite · carolhmj/babylonjs-webpack-es6 (github.com)

1 Like

It worked great! how did you figured that? I have a problem with another one

Uncaught TypeError: _a.createExternalTexture is not a function

using VideoTexture

All credits to Raanan’s original template since it already had the import, but one technique that you can try to resolve these import issues is to look at the code of the function’s stack trace and see if there is anything dynamically loaded there (which isn’t very intuitive, I have to say). In the case of createCubeTextureBase, it does need a loader here:

The ThinEngine._TextureLoaders array is populated when you import the texture loader:

I think we could at least warn the user in case a loader is not found, so I’ll open a PR for that.

About the video texture, doing this method of peeking into the code, I see that the failing line is this:


So I did a code search for createExternalTexture and saw that it is defined in Textures/htmlElementTexture

Going from this, I added:

import "@babylonjs/core/Materials/Textures/htmlElementTexture";

to the code and it solved the issue :slight_smile: Again, this is another place I think we could warn the user in case the function is not defined.

And here is the PR for these two cases, cube texture and video texture: Add warning messages for situations where the user might have forgott… by carolhmj · Pull Request #14635 · BabylonJS/Babylon.js (github.com) :slight_smile:

There are a bunch of places this happens. For example, if you want to use Scene.createDefaultCamera, then you need to import import '@babylonjs/core/Helpers/sceneHelpers';. I follow the method @carolhmj suggested and have found it isn’t terribly difficult to identify what you are missing. Would be nice to have warnings for all these cases, though.

You can just do:

import "@babylonjs/core/Engines/Extensions/engine.externalTexture"; to fix the missing createExternalTexture function on the engine.

Hmmm, the sceneHelpers case is a bit more complicated because the functions are not defined on Scene, but in SceneHelpers. To log a warning, we’d have to move the definitions to Scene, and we try avoiding that, because it makes the class itself larger.

Yep. I think maybe just having something in docs that annotates that using a particular function requires importing a specific package (or subpackage) would be helpful. Similar to how in Unity or Unreal docs it tells you what header file is needed for a specific component.

1 Like