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

Documentation: Needs full example of web-sys DOM #1034

Closed
David-OConnor opened this issue Nov 16, 2018 · 27 comments
Closed

Documentation: Needs full example of web-sys DOM #1034

David-OConnor opened this issue Nov 16, 2018 · 27 comments

Comments

@David-OConnor
Copy link
Member

David-OConnor commented Nov 16, 2018

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 )

@limira
Copy link
Contributor

limira commented Nov 17, 2018

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.

@TitanThinktank
Copy link

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.

@David-OConnor
Copy link
Member Author

David-OConnor commented Nov 21, 2018

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.

@afdw
Copy link
Contributor

afdw commented Nov 21, 2018

@ibaryshnikov
Copy link
Member

@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.

@alexcrichton
Copy link
Contributor

@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!)

@David-OConnor
Copy link
Member Author

David-OConnor commented Nov 26, 2018

@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: rustwasm/wasm-pack#317

@TitanThinktank
Copy link

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.

@alexcrichton
Copy link
Contributor

@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?

@David-OConnor
Copy link
Member Author

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

@Pauan
Copy link
Contributor

Pauan commented Nov 29, 2018

@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?

@TitanThinktank
Copy link

TitanThinktank commented Nov 29, 2018

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
;-)
:-)

@TitanThinktank
Copy link

TitanThinktank commented Nov 30, 2018

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 ?

@David-OConnor
Copy link
Member Author

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

@ibaryshnikov
Copy link
Member

@TitanThinktank
Copy link

TitanThinktank commented Dec 1, 2018

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,

<script src='./hello.js'> wasm_bindgen('./hello_bg.wasm') ..... </script>

@David-OConnor
Copy link
Member Author

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.

@Pauan
Copy link
Contributor

Pauan commented Dec 1, 2018

@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.

@limira
Copy link
Contributor

limira commented Dec 1, 2018

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).

@David-OConnor
Copy link
Member Author

David-OConnor commented Dec 1, 2018

@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
Copy link
Contributor

limira commented Dec 1, 2018

@David-OConnor
Copy link
Member Author

David-OConnor commented Dec 1, 2018

@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>

@limira
Copy link
Contributor

limira commented Dec 1, 2018

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

@TitanThinktank
Copy link

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.

@ibaryshnikov
Copy link
Member

Usually I use https

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

@TitanThinktank
Copy link

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.

@alexcrichton
Copy link
Contributor

I believe this issue is now best served by #446, so closingi n favor of that.

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

7 participants