What are good tools for minimizing bundle size?

I build my BJS App using ES6 tree-shaking feature with Webpack:

-rw-------. 1 u0_a567 u0_a567 7.2M Jan 19 03:22 index.js

7.2mb. Nothing to special, math functions, scene, no sounds, no physics, but, yeah, there is a GUI (which is +2mb).

Ok, let’s try javascript-obfuscator and uglifyjs.

$ javascript-obfuscator --simplify true --options-preset "high-obfuscation" --rename-globals true index.js -o jsobfuscator_output_index.js
-rw-------. 1 u0_a567 u0_a567 4.4M Jan 19 03:30 jsobfuscator_output_index.js
$ uglifyjs index.js -o uglifyjs_output_index.js
-rw-------. 1 u0_a567 u0_a567 3.8M Jan 19 03:25 uglifyjs_output_index.js
$ uglifyjs --compress index.js -o output_index_compressed.js

ok, it have been working for 22 minutes already and I don’t know when it will done.

Gzipped versions:

-rw-------. 1 u0_a567 u0_a567 1.1M Jan 19 05:06 jsobfuscator_output_index.js.gz
-rw-------. 1 u0_a567 u0_a567 651K Jan 19 05:06 uglifyjs_output_index.js.gz

…better obfuscating or less secure but faster loading speed… :smile:
BTW: index.js 7.2mb -> uglifyjs -> gzip -> 651kb. Looks weird :smile:

What tools and its options do you use for minimizing a bundle size?

I wondered this too, how to get just the features I need.

cc @RaananW and @ryantrem

Usually terser does a great job at minifying/“trimming the fat” out this is the default in webpack/rollup

1 Like

Yep, I would recommend terser as well. It is well integrated in the tools and wonderfully configurable.
I would also recommend using dynamic loading and chunks to allow the user to download what they need when they need it instead of a single large package with all dependencies.

Just wondering - what looks weird? is it too much or too little?

1 Like

From 7.2mb to 652kb it’s a huge compression :grinning: it’s great :grinning:

That’s interesting approach. I don’t know actually is it improve loading process or not. Depends on current project I think. But I definitely should give it a try. As for now I don’t think it’s profitable approach for my projects as I think my projects load all the dependencies right at the start :smiley: In this way the speed of loading will decrease because of many requests making to a server for all of those dependencies + an additional delay for loading each module.

Parallel downloading of resources will result in a faster load of your page. Better yet - loading only what is needed for your opening screen, and downloading the rest while the user interacts with whatever on the opening screen is a wonderful approach for a fast, intuitive, and user-friendly website :slight_smile:

1 Like

Wow, I didn’t think about it. Definitely I should try to use soon!

I remember as I had been figthing with my webpack for 2 days to avoid creating chunks. So now it’s time to try to turn it back :smile: Thanks for your thoughts on this subject!

1 Like

Another consideration is that Babylon currently uses side effects quite a bit, which means if you aren’t careful with your imports, you can easily pull stuff in that is never actually used at runtime. For our new Babylon Viewer, I used code coverage tools (I used Istanbul, maybe Chrome Dev Tools code coverage would be enough in your case) to find code that wasn’t being executed, then some custom tooling leveraging Rollup to understand why different modules were ending up in the bundle (e.g. the import chain). @sebavan also suggested https://webpack.github.io/analyse/ might be helpful for bundles created with WebPack, but I haven’t tried it yet.

2 Likes

https://esbuild.github.io/api/#minify

2 Likes

Do we feed terser stuff from here? Babylon.js docs
I don’t understand how to “tree shake”, seems overly complicated.

Sorry, I don’t understand what are you talking about. Tree shaking feature works in another way. Here is the setup for ES6 tree shaking: Babylon.js docs
Nothing complex there! You just need to include “very precise” imports like:

import { HemisphericLight } from "@babylonjs/core/Lights/hemisphericLight";

and avoid imports for the whole your project like this:

import { HemisphericLight } from "@babylonjs/core";

← in this case you will import all the BJS code in your bundle.

Then, don’t forget to set in your webpack.config.js:

optimization: {
    usedExports: true,
},

in case you use webpack. Or something similar if you use Vite or other bundlers.

1 Like

Okay I’ll try that.

Where is the list of these? All I can find is random examples unless Babylon.js/packages/public/@babylonjs/core at master · BabylonJS/Babylon.js · GitHub is comprehensive…

It just offers by your IDE. Or you can see this manually. In my case I use NVim (CoC-Typescript) it looks like this:


Or the same in VSCode.

1 Like

Yeah, and don’t forget about some “silent” imports that you should import because some thing will not work without it. You find them in that ES6 article or find by yourself using IDE suggestions. Here are some of them:

import "@babylonjs/core/Meshes/instancedMesh";
import "@babylonjs/core/Rendering/boundingBoxRenderer";
// import "@babylonjs/core/Culling/ray";
import "@babylonjs/core/Collisions"
import "@babylonjs/core/Layers/effectLayerSceneComponent";
// import "@babylonjs/core/Layers/glowLayer";
// import "@babylonjs/core/Layers/highlightLayer";
// import "@babylonjs/core/Layers";
import "@babylonjs/core/Rendering/outlineRenderer";

One more trick: if some feature is not working then I import some global package like:

import "@babylonjs/core/Layers";

If all worked fine, then I look for more detailed import to specify the concrete package that I miss.

1 Like

There is usage of terser in babylon codebase, but not fully sure if the cdn uses it.

1 Like

That’s definitely the best links than all techniques those I wrote at the first post :grinning: just tried it, works great! Easy and effective.

1 Like

Hrm, I’m lost. I’ll just try to use every available feature to justify loading the whole thing.
Thanks guys :wink:

Just ask if you have any questions! @withADoveInOneHand

1 Like

Would be great to know which part is not understandable, so we can improve the docs and provide our users with everything they need to get what they want.

The general idea of tree shaking is - don’t import the entire framework, just import what you actually need. The rest of the work is done using your bundler (if you use one). Terser/webpack/rollup/vite - these are just tools that will do the magic of bundling, minifying and so on to your code.