Wasm-bindgen: Documentation: Needs full example of web-sys DOM

Created on 16 Nov 2018  ·  27Comments  ·  Source: rustwasm/wasm-bindgen

The Websys section of the official guide includes how to build WASM modules, but not how you'd use in a webpage. For example, if I create an HTML file, serve it, and add <script type="module" src="my_module.js"></script>, I receive the error in browser console: Loading failed for the module with source “http://localhost:8000/my_module_bg”.

I've found I can get it working using Webpack 4, with a minimal package.json, webpack.config.js, and but is there a way to do this without using the Webpack and npm ecosystem, eg pure Rust?

index.html includes: <script type="module" src="main.js"></script>

package.json:

{
  "name": "my_module",
  "license": "MIT",
  "version": "0.1.0",
  "dependencies": {},
  "scripts": {
    "serve": "webpack-dev-server"
  },
  "devDependencies": {
    "webpack": "^4.15.1",
    "webpack-cli": "^3.0.8",
    "webpack-dev-server": "^3.1.4"
  }
}

webpack.config.js:

const path = require('path');

module.exports = {
    entry: path.join(__dirname, 'main.ts'),
    output: {
        filename: 'main.js',
        path: __dirname
    },
    module: {
        rules: [
            {
                exclude: /node_modules/,
            },
        ],

    },
    resolve: {
        extensions: [".tsx", ".ts", ".js", ".wasm"]
    },
    mode: "development"
};

main.ts:

const rust = import("./my_module");

rust.then(r => r.run())

Stated another way: How can I replace the above code with this line in index.html? <script type="module" src="my_module.js"></script> (or .wasm, or _bg.wasm )

Most helpful comment

please someone do that, not everyone going after wasm is JS programmer and many of us are not web developers just because we hate JS and Node; we need to write our programs in Rust, not node.
Thank you.

All 27 comments

Glad to see there are also someone that want to able to use wasm-bindgen without the need of nodejs/webpack. As far as I know, unfornately, it is not easy to do what you want. The browsers today not fully support .wasm files yet. We need to load it and instantiate it. Currently, I known 2 ways doing it:

  1. wasm-bindgen --no-modules and use it directly, or
  2. wasm-bindgen --browser then use wasm2es6js to generate shim like wasm-bindgen-test-runner do

If you go with --no-modules, you will not able to use #[wasm_bindgen(module ="...")]. On the other hand, wasm-bindgen --browser combine with wasm2es6js allow #[wasm_bindgen(module ="...")], but there is a warning from wasm2es6js. Also, you need something like this as a entry point for your wasm-app.

please someone do that, not everyone going after wasm is JS programmer and many of us are not web developers just because we hate JS and Node; we need to write our programs in Rust, not node.
Thank you.

Glad to see there are also someone that want to able to use wasm-bindgen without the need of nodejs/webpack. As far as I know, unfornately, it is not easy to do what you want. The browsers today not fully support .wasm files yet. We need to load it and instantiate it. Currently, I known 2 ways doing it:

1. `wasm-bindgen --no-modules` and use it directly, or

2. `wasm-bindgen --browser` then use `wasm2es6js` to generate shim like [`wasm-bindgen-test-runner` do](https://github.com/rustwasm/wasm-bindgen/blob/master/crates/cli/src/bin/wasm-bindgen-test-runner/server.rs#L58-L60)

If you go with --no-modules, you will not able to use #[wasm_bindgen(module ="...")]. On the other hand, wasm-bindgen --browser combine with wasm2es6js allow #[wasm_bindgen(module ="...")], but there is a warning from wasm2es6js. Also, you need something like this as a entry point for your wasm-app.

Do you have more details on option 1? Unable to get it working as-is. Option 2 seems messier than the JS workaround I mentioned.

@TitanThinktank i created a pr, but it's likely to be closed. Anyway, you can grab the example from the diff, or even take it to your own repo.

@David-OConnor thanks for the report! Can you elaborate on how --no-modules isn't working though? That's the intended use case here for using wasm-bindgen without ES modules and such.

(eventually when browsers support wasm-as-ES-modules this'll work more seamlessly!)

@alexcrichton Gave it another shot just now... Working as advertised, on Chrome and FF, although not Edge! (Of note I'm now getting a MIME-type error with the webpack dev server, but the Rust HTTPS server works; related: These are the only dev servers I've ever been able to get working with WASM, due to MIME issues) I must have made a mistake or left something out on my first attempt

For someone not familiar with the dets of ES modules, this quote, is a bit confusing: "It supports working without ES modules, however! Not all JS tooling and browsers are ready for ES modules by default," : The first sentence implies working without ES modules is the shimless version we've been discussing. The second appears to imply the opposite. I'm probably missing something, but I suspect others new to this might have the same reaction.

Lately, I've been using wasm-pack to build due to its simpler CLI, but it looks like it doesn't support --no-modules yet. (Haven't dug through the source, but it seems to mainly wrap the build and wasm-bindgen commands, so this should be straightfwd to implement). Relevant: https://github.com/rustwasm/wasm-pack/issues/317

i am a total newbie but if this can help, https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API#Some_simple_examples.

if anyone can use that "fetch" to load the wasmpack generated .wasm file with it, it might make things bearable.

i am asking here, so a reply regarding fetch() would be of great help.

@David-OConnor oh ok good to know that it works! Can you gist the error message you're seeing in Edge? That sounds like a bug!

@TitanThinktank we already use fetch internally along with instantiateStreaming wherever you can, so can you elaborate a bit on what you're looking for?

@alexcrichton
SCRIPT5009: SCRIPT5009: 'TextDecoder' is not defined
SCRIPT5009: SCRIPT5009: 'wasm_bindgen' is not defined

@David-OConnor That's because wasm-bindgen uses TextDecoder and TextEncoder to convert from UTF-8 strings to UTF-16 (and vice versa).

Those APIs are supported in all major browsers except for Edge, which is why you're getting that error. So you'll need a polyfill.

Perhaps wasm-bindgen should auto-include a polyfill for TextEncoder and TextDecoder?

Thanks to all those who replied here, it has helped, but i am new to JS and hence web development itself though i am a old school programmer, the mention of webpack stopped me in my tracks, and meer mention of Node or npm irritates me, its my personal problem,
also now i wonder if this is a new addition to the book, https://rustwasm.github.io/wasm-bindgen/reference/no-esm.html , since some how i missed it before , that html code in it is very important.

if below two line were not there in the introduction i would had been encapsulating html through Rust objects by now,
$ npm install
$ npm run serve
;-)
:-)

i have not yet seen the light of wasm-bindgen "hello world" working on my machine till now, i hope someone creates a step by step tutorial without the damn mention of Node or npm.

Also judging by the comments and issues raised here, it seems things are working for other people here, this is very sad for me.

is there any other IRC or forum where i can ask such questions ?

@TitanThinktank Are you trying to call rust funcs from JS, build a webpage entirely in Rust, or something else?

ibaryshnikov, why are you posting that link, why will anyone use a build.sh, i am learning how to do wasm,
how will anyone learn about wasm by using a build.sh ? Thats the exact problem why i am not going for things related to webpack, i dont even know whats webpack, it seem to be something for node, a huge distraction in learning, why make newbies worry about whats in the package.json or webpack.config.js, these things have got nothing to do with WebAssembly. So much ceremony to follow and even a helloworld program wont work.

David-OConnor , it seems that --no-modules example wont work without a webserver, thats not how it should be, its a problem of ES6. And i understood that only by combining the two Script tags given here, https://rustwasm.github.io/wasm-bindgen/reference/no-esm.html
like this,

I have not found a way to run WASM from an HTML file alone without a server; it seems as if doing so is on its way out in general.

@TitanThinktank The build.sh file is tiny:

#!/bin/sh

set -ex

cargo build --target wasm32-unknown-unknown

cargo run --manifest-path ../../crates/cli/Cargo.toml \
  --bin wasm-bindgen -- \
  --no-modules \
  ../../target/wasm32-unknown-unknown/debug/no_modules.wasm --out-dir .

python -m SimpleHTTPServer

All it does is run some cargo and wasm-bindgen commands and then starts up a local web server.

You don't need to use the build.sh, you can run the commands manually if you wish.

why make newbies worry about whats in the package.json or webpack.config.js, these things have got nothing to do with WebAssembly.

All useful WebAssembly programs need to contain JavaScript code.

And so to avoid reinventing the wheel, we use standard JavaScript tools (npm, Node, and Webpack) to manage the JavaScript code.

Similarly, we use standard Rust tools (Cargo) to manage the Rust code.

If you wish to completely avoid npm, Node, and Webpack, the no_modules link that @ibaryshnikov posted is the right way to do it.

it seems that --no-modules example wont work without a webserver, thats not how it should be, its a problem of ES6.

No, it has nothing to do with ES6 (or Rust, or npm, or Node, or Webpack, or wasm-bindgen).

It is a limitation in WebAssembly itself: web browsers will refuse to load a WebAssembly file which does not have a MIME type of application/wasm.

That is why you must use a local web server to test the code.

The build.sh file is tiny

I did try to explain it, but I am so slow and @Paun beats me. In other words: the mentioned build.sh contains step-by-step commands that you can run each of them in the terminal. The author just put all of them into one custom command so that you can run by typing ./build.sh in your terminal. If you want to run each of them manually, just ignore the first command set -ex.

As you already known. The app need a local server, and the build.sh use python -m SimpleHTTPServer. To my surprise, it is already available on my system (Fedora 28, and I do not directly use anything python-related stuff).

@limira How'd you get it working with Python's server? (Python3 command is python -m http.server) I get a MIME type error when using it.

@limira Thanks - after adding the first script section of that file, it now works with both Python's server, and opening the html file directly.

Of note, the code in the third script section is quite different from what I'm using, which I got from a diff wasm_bindgen example.

    <script>
        // the `wasm_bindgen` global is set to the exports of the Rust module
        const { render } = wasm_bindgen;
        // we'll defer our execution until the wasm is ready to go
        function run() {
            render();
        }
        // here we tell bindgen the path to the wasm file so it can run
        // initialization and return to us a promise when it's done
        wasm_bindgen('./pkg/rebar_bg.wasm')
          .then(run)
          .catch(console.error);
    </script>

Oh, I never need to open the html file directly so I totally forget that deleting WebAssembly.instantiateStreaming make it works.

since i dont want to waste time learning about Python server, i have nothing more to say about build.sh, instead i will put that time reading something about rust web apps which can help serve wasm files, and i bet that wont need anything about webpack.

Usually I use https

cargo install https
# then navigate to your folder and run
http

By limiting wasm to server content, that wont keep nodeJS alive , but it will kill the webbrowsers for sure and my guess is that the wasm developers wont like that future for their webbrowsers.
https://github.com/Geal/serverless-wasm

Although i will love to thrive in such a future, in fact finally web will become free from WebBrowsers as a defacto platform.

I believe this issue is now best served by https://github.com/rustwasm/wasm-bindgen/issues/446, so closingi n favor of that.

Was this page helpful?
0 / 5 - 0 ratings