Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

failed to load wasm application

I'm trying to host a website, and I use a .wasm file with .js scripts created by the wasm-pack tool.

I tested the project locally with npm and node.js and everything worked fine.

But Then I hosted it on a raspberry (apache2), and when I try to access it, I get in the following error:

Failed to load module script: The server responded with a non-JavaScript MIME type of "application/wasm". Strict MIME type checking is enforced for module scripts per HTML spec.

details

There are multiple files, but here is the idea:

my index.html loads the module bootstrap.js

// bootstrap.js content
import("./index.js").catch(e => console.error("Error importing `index.js`:", e));

my main code is in the index.js, which calls test_wasm_bg.js

And finally, test_wasm_bg.js loads the wasm file with this line:

// test_wasm_bg.js first line
import * as wasm from './test_wasm_bg.wasm';

Where is the problem?

What is the right way to load a web assembly file?

like image 349
rambi Avatar asked Dec 18 '22 12:12

rambi


1 Answers

I finally found what is the right way to load a wasm application in a wasm-bindgen project!

In fact, everything was on this page

When you compile the project without wanting to run it with a bundler, you have to run wasm-pack build with a --target flag.

wasm-pack build --release --target web.

This creates a .js file (pkg/test_wasm.js in my example) with everything you need to load the wasm-application.

And then this is how you use the functions created by wasm-bindgen (index.js):

import init from './pkg/test_wasm.js';
import {ex_function, ex_Struct ...} from '../pkg/test_wasm.js';

function run {
    // use the function ex_function1 here

}

init().then(run)

You include your index.js in your HTML file

<script type="module" src="./index.js"></script>

And then it work's !

Edit:

Now that's I understand the javascript ecosystem a bit more, I cab try to explain what I understand: There are many ways to do imports in js, here is a list : https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm

You don't need to know much about that, except that the default target of wasm-pack is a node style ecmascript module. This import will work in node.js, but not directly in the browser. So in node, you can import a function from a wasm file directly, like so: import {ex_function} from "./test.wasm"

But these styles of import don't work in the browser right now. Maybe it will be possible in the future But for now, your browser only knows about js modules. So if you try to import a .wasm file directly in the browser, it will throw a mime type error because it doesn't know how to deal with webassembly files.

The tool you use to go from ecmascipt modules (with a lot of nmp packages for example) to a single js file is called a web-bundler (webpack, rollup, snowpack ...). If you work on a big project with npm, you probably need one. Otherwise, the "--target web" will say to wasm-bindgen to instantiate the wasm module the right way (look at the pkg/test_wasm.js)

like image 116
rambi Avatar answered Jan 01 '23 20:01

rambi