Large bundle size

I’m getting insanely large bundle sizes, like over 20MB dev, and 10MB prod. The project uses es6 modules, so tree shaking should eliminate unused code, but there’s over 8MB of orphan modules. TBH, even without them we’re looking at over 1.5MB, but at this point I’m willing to live with that.

I based my setup off https://github.com/RaananW/babylonjs-webpack-es6, which produces 647KB bundles… What did I mess up?

> webpack --config webpack.prod.js

asset all.js 9.68 MiB [emitted] [minimized] [big] (name: main) 1 related asset
asset index.html 147 bytes [compared for emit]
orphan modules 8.01 MiB [orphan] 1058 modules
runtime modules 1.17 KiB 6 modules
cacheable modules 20.7 MiB
  modules by path ./node_modules/@babylonjs/core/ 10.1 MiB 305 modules

package.json

 "dependencies": {
    "@babylonjs/core": "^5.9.0",
    "@babylonjs/gui": "^5.9.0",
    "@babylonjs/inspector": "^5.9.0",
    "earcut": "^2.2.3"
  }

tsconfig.json

"target": "es2016",
"module": "es6",
"moduleResolution": "node",
"skipLibCheck": true

webpack.common.js

const path = require("path");
const fs = require("fs");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const appDirectory = fs.realpathSync(process.cwd());

module.exports = {
    entry: path.resolve(appDirectory, "src/index.ts"), //path to the main .ts file
    output: {
        filename: "all.js", //name for the javascript file that is created/compiled in memory
        path: path.resolve(__dirname, 'dist'),
        clean: true
    },
    resolve: {
        extensions: [".tsx", ".ts", ".js"],
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: "ts-loader",
                exclude: /node_modules/,
            },
            {
                test: /\.css$/,
                use: ["style-loader", "css-loader"]
            },
            {
                test: /\.(png|jpg|jpeg|gif)/,
                use: ["image-loader"]
            }
        ],
    },
    plugins: [
        new HtmlWebpackPlugin({template: 'www/index.html'})
    ]
};

webpack.prod.js

const { merge } = require('webpack-merge');
const common = require('./webpack.common.js')

module.exports = merge(common, {
    mode: 'production'
});

cc @RaananW

That is probably the inspector! though I can’t really tell without seeing your actual code. Would you be able to share your project?

2 Likes

Dropping the inspector brought the bundle size down to 4.39 MiB.

I made a bare-bones copy of the project, and posted it at GitHub - alekop/projx-copy.

Our current package is built with side effects so importing from /core : import { Engine, Scene } from "@babylonjs/core" will result in importing the entire package. You should split your import at the module level to ensure to benefit from tree shaking.

@RaananW is actively working on finding an awesome alternative.

1 Like

I replaced all things like import { Mesh } from "@babylonjs/core" with more specific ones, like import { Mesh } from "@babylonjs/core/Meshes/mesh"… Now the bundle size went up to 56 MiB! LOL

And there are tons warnings like:

ModuleConcatenation bailout: Cannot concat with ./node_modules/@babylonjs/gui-editor/node_modules/@babylonjs/core/Maths/math.frustum.js: Module ./node_modules/@babylonjs/gui-editor/node_modules/@babylonjs/core/index.js is referenced from these modules with unsupported syntax: ./node_modules/@babylonjs/gui-editor/dist/babylon.guiEditor.max.js (referenced with cjs require)

I just don’t understand what’s different about my setup vs RaananW’s.

@RaananW should be able to have a quick look tomorrow

This is due to a mismatch in versions between the installed @babylonjs/core and some other package. probably the inspector, unless you are using the gui-editor package directly. can you make sure all versions of the dependencies match? i.e. run npm update, after makig sure the version in package.json matches.

1 Like

Here’s a fork of your repo with bundle size 466 KB. Importing each class from its path brought it down to 1.5 MB, enabling the minimizer brought it down the rest of the way. :slight_smile:

1 Like

After replacing all imports, the bundle size has dropped to about 4.5MB for dev, and 1.3 MB for prod. Not great, but a major improvement.

But importing the inspector brings it back to 57 MB, even though the babylon.inspector.bundle.max.js is 5.1 MB. FWIW, the inspector is import conditionally - I’m not sure if that makes a difference.

if (_DEBUG) {
    require("@babylonjs/inspector")
}

you can async-import it to separate it from the main bundle. That owuld be my recommendation in that case. The inspector is thought to be a debugging tool, so we didn’t make package size a priority. Of course, it shouldn’t increase so much, and we will work in the future on improving this.

2 Likes