BabylonJS / Babylon.js

Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.
http://www.babylonjs.com
Apache License 2.0
23.24k stars 3.43k forks source link

Add full support for ES6 modules (for Gui and Inspector) #3314

Closed deltakosh closed 5 years ago

deltakosh commented 6 years ago

Let's open the door to tree Shacking ;)

RaananW commented 6 years ago

Starting 3.2.0-alpha2 on NPM we have es6 modules available in beta. I am keeping this open until I am satisfied there are no bugs.

edzis commented 6 years ago

@RaananW I get TypeError: Cannot set property 'FreeCameraGamepadInput' of undefined.

I think this is because CameraInputTypes is not defined. When searching in the resulting JS code I can not find where it is created.

RaananW commented 6 years ago

Thanks! CameraInputTypes is a part of the targetCamera module, which the FreeCamera depends on. let me check why it is not automatically included. Could you try importing CameraInputTypes from "targetCamera" and see if it exists? Also - es6, or commonjs?

RaananW commented 6 years ago

I assume you are using es6, and I believe I know what the problem is. Fix is coming soon, thanks for reporting!

edzis commented 6 years ago

That is what I just tried and got by bay adding

import { CameraInputTypes } from 'babylonjs/targetCamera'
console.log('CameraInputTypes', CameraInputTypes)

in front of my import of Gamepad

But now getting other errors which I will look into working around and report back here.

edzis commented 6 years ago

Next one I get is

Uncaught TypeError: BABYLON.VRExperienceHelper is not a constructor
at Scene../node_modules/babylonjs/core/index.js.Scene.createDefaultVRExperience

VRExperienceHelper is not imported in core.

RaananW commented 6 years ago

Core will have a few classes missing, that will need to be imported and added. This will be a part of the documentation when I write it. We do try to prevent importing everything to core while still keeping backwards compatibility. The Scene will slowly be cleaned from unneeded dependencies, but for now we will need to import those missing classes.

And I just noticed I have a small bug with es6 libs that depend on modules that are not core. Which will probably be the main source of errors in es6.

edzis commented 6 years ago

I will look out for any es6 updates and test again.

Not sure if this is helpful now, but I just noticed that after switching to es6 babylon on my 10 files the production bundle grew quite a bit - 850.62 KB (+283.2 KB) build/static/js/main.c19e52b2.js

RaananW commented 6 years ago

Thanks for the info, I will keep you updated here. Quick question - what lib are you using to bundle your package?

edzis commented 6 years ago

I am using webpack as configured by Create React App with TypeScript support

create-react-app my-app --scripts-version=react-scripts-ts

browsermage commented 6 years ago

import { ArcRotateCamera } from '../node_modules/babylonjs/arcRotateCamera/es6.js' gives error Uncaught TypeError: Failed to resolve module specifier 'babylonjs/targetCamera/es6' as on line 19, there is: import * as targetCamera from 'babylonjs/targetCamera/es6'; I'm not using any bundler, so I am curios is this a oversight or will I not be able to use native js? ( I understand it's a alpha :) I am just curios keep up the good work)

RaananW commented 6 years ago

Wow, super question!!

I believe that eventually we will support native javascript with es6 and leave commonjs to the bundlers. That's the entire point of supporting es6 :smile: The problem is the lack of standard (at least one that I know of) in terms of location of the js files. Should I add "./node_modules/", should I create a form of a packer? All interesting questions that will be slowly answered!

We have internally decided to first support es6 with a single large file (the entire framework with es6 exports), so people will be able to start working with native es6.

Most bugs were already eliminated (but not yet merged), and I am working on a solution for circular dependencies. It will sadly take longer than I expected...

edzis commented 6 years ago

@RaananW I just upgraded to alpha4 and it fails to locate modules:

import { Engine, Scene, Texture, Tools } from 'babylonjs/core'

results into

[ts] Cannot find module 'babylonjs/core'
RaananW commented 6 years ago

Until I fix the entire build process, I have decided to remove the modules. Instead of using babylonjs/core , please use babylonjs . It will load the entire framework. It is not optimal, but it works and tested. Native es6 can be loading using: import { Whatever } from 'babylonjs/es6'

I will keep this thread updated when the modules are back and working. Sorry about the hassle!

cruzdanilo commented 6 years ago

using babylonjs v3.2.0-alphaB and webpack v4.1.0:

import { Space } from 'babylonjs/es6';
console.log(Space); // undefined

webpack gives this:

WARNING in ./main.js
2:12-17 "export 'Space' was not found in 'babylonjs/es6'
 @ ./main.js
deltakosh commented 6 years ago

Pinging @raananw

RaananW commented 6 years ago

Problem found, I will take care of that until the next npm release.

cruzdanilo commented 6 years ago

@RaananW, i also had to use this hack in my webpack.config.js for shaking off oimo and cannon:

  plugins: [
    new DefinePlugin({ OIMO: JSON.stringify(true), CANNON: JSON.stringify(true) }),
  ],

webpack v4.1.0

RaananW commented 6 years ago

I am planning on fixing the cannon and oimo dependencies in a different way. But a question - why are you using the es6 module if you use webpack? the UMD would fit much better. ES6 was mainly created for native es6 developers.

cruzdanilo commented 6 years ago

i was just trying the new stuff :) but the oimo/cannon hack is necessary using umd too. also, it is less weird to write import { Engine } from 'babylonjs/es6' than import { Engine } from 'babylonjs/babylon.max'. the minified version gives less accurate build size stats.

RaananW commented 6 years ago

(I am just asking, not criticizing at all :smile:). What problem do you have with the minified version? not sure what you mean with the build size stats.

About Oimo and Cannon, I will soon add them as peer dependencies to the main engine so you can define them as externals in webpack.

cruzdanilo commented 6 years ago

take a look at the demo here: https://chrisbateman.github.io/webpack-visualizer/ the 'actual vs raw' size is less accurate when using pre-minified code.

cruzdanilo commented 6 years ago

nice source maps for debugging are also a huge plus.

deltakosh commented 6 years ago

Moving to 3.3 as we need to refactor a lot of code

robinfehr commented 6 years ago

@RaananW using a bundler e.g. webpack i guess is a good idea with the es6 version here since not only can we do the tree-shaking that does include what we need but also eliminate the dead code and cut it from the files. therefore end up with a much smaller bundle. as of webpack4(i guess 4 :~)) there is also a option that can be added to the package.json to tell the bundler about sideEffects and make the dead code deleteable by default if not imported. therefore specifying the files as sideEffectFree if thats the case could drastically reduce the bundle size.

haven't tested it yet though. but might be worth a try.

https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free

kutomer commented 6 years ago

@RaananW That's awesome, the way I see it this is the most important feature you guys can add to babylonjs. currently babylonjs source code is 64.4% (3.2.0-beta.4 without physics engine - 1.86mb) of my bundle. Can't wait for this feature to be released officially, so keep up the good work :)

When I try to import modules from babylonjs/es6 I get an error message -

error TS7016: Could not find a declaration file for module 'babylonjs/es6'. '/.../node_modules/babylonjs/es6.js' implicitly has an 'any' type.
  Try `npm install @types/babylonjs/es6` if it exists or add a new declaration (.d.ts) file containing `declare module 'babylonjs/es6';`

Any thoughts? Tomer

brian-hay commented 6 years ago

I assume this error is related to the discussion here and I don't need to create a new issue?

./node_modules/babylonjs/babylon.js
Module not found: Error: Can't resolve 'oimo' in '/path/to/myproject/node_modules/babylonjs'
deltakosh commented 6 years ago

Pinging @raananw

pascalbayer commented 6 years ago

Just gave a try to the new babylonjs/es6 exports in my current @angular/cli project.

Interestingly I get following results:

RaananW commented 6 years ago

Hi @pascalbayer, are you using any other package (loaders, gui, etc) ? since they are not yet es6-enabled, they will load the UMD dependency, so Babylon will technically be included twice. Could that be the case here?

To everyone following this open issue - First, sorry for answering so late. I wish I had better news regarding full framework support of es6. Since out typescript codebase is not es6-compatible we need to refactor a lot of the code to get full support (including typescript declaration, for example). This will take some times, but we are all very much eager to get this feature to you as soon as possible.

My recommendation to everyone would be to use typescript with commonjs using our fully-supported UMD module. you will still be able to import from "babylonjs" and all of its modules, so you can still write es6 code. Using the es6 module is actually only needed if you write es6-code only and are planning on serving es6 to your users. The rest can be done the same using UMD.

@brian-hay - this is actually not related to this issue - you are using babylon.js which is our UMD file. To solve this see here - http://doc.babylonjs.com/features/npm_support#using-webpack

pascalbayer commented 6 years ago

@RaananW Yes, that is actually the case, I 'm including loaders and materials, did a quick check and disabled the two and it worked.

Thanks for the update and the good work. Let me know if there is anything I can do to contribute to a faster es6 feature completion.

kutomer commented 6 years ago

@RaananW Hey, any updates on this one? Need any help? just upgraded to 3.3.0-alpha.3 and still get the same error when trying to import from babylonjs/es6.

 Could not find a declaration file for module 'babylonjs/es6'. '/.../node_modules/babylonjs/es6.js' implicitly has an 'any' type.
  Try `npm install @types/babylonjs/es6` if it exists or add a new declaration (.d.ts) file containing `declare module 'babylonjs/es6';`
RaananW commented 6 years ago

not yet done. as this requires a major change in our codebase. When we'll start working on it I will make sure to reference this issue

BrainBacon commented 6 years ago

Hey guys, I'm looking to get the babylonjs-loaders extension integrated into the es6 build for the Vue-BabylonJS plugin. Right now without it I am unable to proceed with creating an asset component.

From what I understand about the goals with the es6 build, shouldn't all of the first-party extensions just be included in the build? Couldn't one use tree-shaking to just omit that functionality when consuming the library as an ES Module?

Specifically with babylonjs-loaders is something blocking including that particular extension? Can I tackle some refactoring tasks to speed up that piece?

deltakosh commented 6 years ago

Just to make sure: why not referencing both?

BrainBacon commented 6 years ago

From my experiments with including the babylonjs-loaders dependency with the es6 build it seems like an incredible amount of code is being loaded and ended up crashing my Rollup build. Even when I increased the memory limit for Rollup, the resulting bundle size was so great as to crash Webpack in my tests. I assumed this was because Babylon.js is being included twice; by the es6 build and the standard build imported by babylonjs-loaders.

deltakosh commented 6 years ago

Pinging the master of modules @RaananW

BrainBacon commented 6 years ago

Actually, a quick thought; I know this wouldn't solve every use-case, but would it be useful to produce a Webpack Loader in addition to the standard client-side loaders? I'm thinking it would be really efficient to convert .obj, .stl, and .gltf assets to modules or .babylon at build time. Obviously this wouldn't help with assets hosted by third-parties, but would save compute cycles and bundle size on clients that host their own assets.

FabienMorival commented 6 years ago

not sure if it's really related, but when I imported babylonjs from yarn, I got these errors :

./node_modules/babylonjs/babylon.js Module not found: Can't resolve 'cannon' in 'node_modules\babylonjs'

./node_modules/babylonjs/babylon.js Module not found: Can't resolve 'earcut' in 'node_modules\babylonjs'

./node_modules/babylonjs/babylon.js Module not found: Can't resolve 'oimo' in 'node_modules\babylonjs'

BrainBacon commented 6 years ago

@FlynnTheInfinite It's because cannon, earcut, and oimo are now optional peer dependencies. You can add them to your project dependencies and the UMD module definition should pick them up. There's more details in the documentation.

RaananW commented 6 years ago

We are slowly moving the modules to es6-style code. GUI and Inspector will soon be integrated, next are the materials and loaders - https://github.com/BabylonJS/Babylon.js/pull/4738

BrainBacon commented 6 years ago

Excellent, thanks for the update. Let me know if there's anything you would like me to try and tackle.

kutomer commented 6 years ago

@RaananW Hey, Thanks a lot for that! But not sure how to use it, I'm using version 3.3.0-alpha.15 When I try to import the module: import { AdvancedDynamicTexture } from 'babylonjs-gui/2D/advancedDynamicTexture'; I get no definition errors. But when I try to compile I get the following error:

Failed to compile.

Module not found: Error: Can't resolve 'babylonjs-gui/2D/advancedDynamicTexture' in ...

Not sure how it suppose to work, but I expected the node_module dir to look something like lodash.

(I'm using only advancedDynamicTexture and button and it's taking 186kb)

RaananW commented 6 years ago

Hi,

The GUI's package is still a umd package. The next step, until 3.3.0 official release, is to also include an es6 compatible bundle which will allow you to do what you are trying to do. ATM you still need to import everything from "babylonjs-gui".

NPM will include both umd and es6, so you will be able to choose what you are using. It's use the "esnext" and "module" tag to separate the two.

kutomer commented 6 years ago

@RaananW Thanks for your quick reply, but not sure I fully understood what you meant :) How do I select the es6 bundle? I don't see any "es6" bundle in babylonjs-gui folder in node_modules (version alpha.15) screen shot 2018-08-05 at 15 15 18

RaananW commented 6 years ago

There isn't any es6 package yet. This is the next step, after converting the code to es6 compatible. I'll update better when we deliver the es6 bundle. At the moment it's umd only

deltakosh commented 6 years ago

For 3.3 we will move Gui and Inspector. Another task was created for the core engine

kutomer commented 6 years ago

So now import { AdvancedDynamicTexture } from 'babylonjs-gui'; should trigger tree shaking?

deltakosh commented 6 years ago

It will as soon as we will finish this task

deltakosh commented 6 years ago

Hey @RaananW, do you think this could be done for 3.3 time frame?