Search code examples
rustwebassemblywebgl2wasm-bindgenbevy

Error running a Bevy game in browser: "WebAssembly.instantiate(): Import #0 module="wbindgen_placeholder" error: module is not an object or function"


I am trying to run a game I built with Bevy and Rust in the browser. Bevy started supporting WebGL2 from version 0.11.0, and I am using this version. I have compiled my Rust code to WebAssembly using wasm-pack build --target web.

However, when I try to initialize the WebAssembly module in my HTML file, I get the following error:

WebAssembly.instantiate(): Import #0 module="__wbindgen_placeholder__" error: module is not an object or function

Here is the JavaScript code I am using to initialize the WebAssembly module:

    import init, { run } from './game.js';

async function main() {
    await init('./game.wasm');
    run();
}

main();

In main.rs I have my run function with the export defined like:

#[wasm_bindgen]
pub fn run() {
    App::new()
        .add_plugins(DefaultPlugins)
    //initialize more systems and resources 
}

I have verified my paths are correct, and I am serving the files using the Live Server extension in VSCode. I am using the latest version of chrome and rust on popOS.

I have also checked the Bevy documentation and examples, but I couldn't find any specific guidance on this issue.

Does anyone know what could be causing this error and how to fix it?


Solution

  • If you want to compile a bevy application to wasm using wasm-pack you need to do it a bit different than usual.

    First of all there is no need to add the #[wasm_bindgen] attribute anywhere in your rust code (e.g. no need to explicetly depend on wasm-bindgen).

    To build your project for the wasm32-unknown-unknown target, run:

    cargo build --release --target wasm32-unknown-unknown
    

    and after that create the JavaScript bindings using wasm-pack and the binary built in the previous step:

    wasm-bindgen --out-dir out --target web target/wasm32-unknown-unknown/release/game.wasm
    

    Lastly serve such an index.html with a http-server of your choice:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>Bevy Game</title>
        <meta charset="UTF-8" />
        <style>
            body {
                background: linear-gradient(135deg,
                        white 0%,
                        white 49%,
                        black 49%,
                        black 51%,
                        white 51%,
                        white 100%);
                background-repeat: repeat;
                background-size: 20px 20px;
            }
    
            canvas {
                background-color: white;
            }
        </style>
    </head>
    <script type="module">
        import init from './out/game.wasm'
        init()
    </script>
    
    </html>
    

    with the relevant part of course being:

    <script type="module">
        import init from './out/game.wasm'
        init()
    </script>
    

    I have a full repository where this workflow is set up over here.