Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webpack issues #374

Open
Kruptein opened this issue Jun 17, 2021 · 9 comments
Open

Webpack issues #374

Kruptein opened this issue Jun 17, 2021 · 9 comments

Comments

@Kruptein
Copy link

Hi there, for the last couple of days I've been struggling with getting this js package to work in a bundled fashion. Both with vue-cli (webpack) and vitejs (rollup) I'm having issues getting it to work properly either at build or runtime.

With webpack for example I'm getting:

TypeError: Cannot set property 'Ammo' of undefined
    at ammo.js:978
    at h.load (diceThrower.js:29)

My own code (diceThrower.js:29) is simply: const ammo = await Ammo();

With the ammo.js error being at the end of the file

        (function() {
            function a() {
                b.BT_CONSTRAINT_ERP = GA();
                b.BT_CONSTRAINT_STOP_ERP = HA();
                b.BT_CONSTRAINT_CFM = IA();
                b.BT_CONSTRAINT_STOP_CFM = JA();
                b.PHY_FLOAT = KA();
                b.PHY_DOUBLE = LA();
                b.PHY_INTEGER = MA();
                b.PHY_SHORT = NA();
                b.PHY_FIXEDPOINT88 = OA();
                b.PHY_UCHAR = PA()
            }
            Ta ? a() : Ra.unshift(a)
        }
        )();
        this.Ammo = b;   // <-- this line

        return Ammo.ready
    }
    );
}
)();
if (typeof exports === 'object' && typeof module === 'object')
    module.exports = Ammo;
else if (typeof define === 'function' && define['amd'])
    define([], function() {
        return Ammo;
    });
else if (typeof exports === 'object')
    exports["Ammo"] = Ammo;

Is there anyone that has a working example with webpack/rollup or some insights into what I might be doing wrong :(

@FX-Wizard
Copy link

I've had the same problem. Depending on which version of webpack your using you can try adding this to your webpack config

Webpack 5:

resolve: {
    fallback: {
        fs: false,
        'path': false, // ammo.js seems to also use path
    }
}

Webpack 4:

node: {
    fs: 'empty'
}

Here's a link to the Babylon.js forums where this issue is discussed more in depth.
https://forum.babylonjs.com/t/ammo-js-webpack-issues/2987

I have not been able to find a way to get it working with vite/rollup. If you figure it out please let us know.

@Kruptein
Copy link
Author

Kruptein commented Sep 1, 2021

For now I've opted for sideloading the ammo.js file manually instead of bundling it with my other dependencies, because I indeed cannot get it to work with vite/rollup.

@kaphula
Copy link

kaphula commented Dec 16, 2021

I am facing the same issue when I try to bundle to library module with Rollup and TypeScript.

@Kruptein How did you "sideload" the ammo.js successfully, or what does this even mean in practice?

@Kruptein
Copy link
Author

Kruptein commented Dec 16, 2021

While digging around I found some library/framework that was using ammo (I can't recall the name) and it did something like this:

(it's far from ideal, but it does the job)

const loadScriptAsync = (url: string): Promise<void> => {
    return new Promise((resolve) => {
        const tag = document.createElement("script");
        tag.onload = () => {
            resolve();
        };
        tag.onerror = () => {
            throw new Error(`failed to load ${url}`);
        };
        tag.async = true;
        tag.src = url;
        document.head.appendChild(tag);
    });
};

export const loadAmmoModule = async (): Promise<void> => {
    // there were some wasm checks here that I never tested out so I don't remember the og source here
    // console.log(wasmSupported ? 'WebAssembly is supported' : 'WebAssembly is not supported')
    // if (wasmSupported) loadScriptAsync(`${path}/ammo.wasm.js`, () => doneCallback())
    await loadScriptAsync("${path}/ammo.js");
};

So basically manually injecting a <script> in the page with a url to the ammojs code on some server you own or that is public.

@kaphula
Copy link

kaphula commented Dec 17, 2021

That's pretty wild. I will give it a try tomorrow. Thanks for sharing!

@TheVirtuoid
Copy link

TheVirtuoid commented Dec 17, 2021

@kaphula yes, this does work. It would be far better to find a vite/rollup solution, but for now at least I'm up and running. Thanks for the sleuthing, @Kruptein.

@DontMash
Copy link

DontMash commented Aug 3, 2022

While digging around I found some library/framework that was using ammo (I can't recall the name) and it did something like this:

(it's far from ideal, but it does the job)

const loadScriptAsync = (url: string): Promise<void> => {
    return new Promise((resolve) => {
        const tag = document.createElement("script");
        tag.onload = () => {
            resolve();
        };
        tag.onerror = () => {
            throw new Error(`failed to load ${url}`);
        };
        tag.async = true;
        tag.src = url;
        document.head.appendChild(tag);
    });
};

export const loadAmmoModule = async (): Promise<void> => {
    // there were some wasm checks here that I never tested out so I don't remember the og source here
    // console.log(wasmSupported ? 'WebAssembly is supported' : 'WebAssembly is not supported')
    // if (wasmSupported) loadScriptAsync(`${path}/ammo.wasm.js`, () => doneCallback())
    await loadScriptAsync("${path}/ammo.js");
};

So basically manually injecting a <script> in the page with a url to the ammojs code on some server you own or that is public.

Credits to: https://github.com/enable3d/enable3d/blob/master/packages/common/src/wasmLoader.ts

@TheVirtuoid
Copy link

Following up on this older post - in case others are having the same problem.

In my application, I am using vite/rollup with BabylonJS / Ammo.js. I am also using the directions on the BabylonJS site for using Ammo.js with the library. In doing so, I get the error mentioned above.

I discovered that I can change my app to this:

// this is suggested code from the BabylonJS site

// OLD (gives error)
import ammo from "ammo.js";
const Ammo = await ammo();

// NEW (removes error)
import ammo from "ammo.js";
const Ammo = await ammo.bind(window)();

By merely binding a new 'this' to the Ammo module, the library loaded correctly.

Hopefully this will help, or at least give you clues in solving your particular issues.

@AlvaroHerreroDev
Copy link

This is what worked for me on an Angular 14 project:

import Ammo from 'ammojs-typed'

export const initPhysics = async (scene: Scene) => {
  const ammo = await Ammo.bind(window)();
  const physics: AmmoJSPlugin = new AmmoJSPlugin(true, ammo)
  scene.enablePhysics(Vector3.Zero(), physics)
}

and

  "browser": {
    "fs": false,
    "path": false
  },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants