diff --git a/.travis.yml b/.travis.yml index fb3d6c3b..023fc9dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,8 @@ script: - cargo install --debug --path crates/wasm-bindgen-cli - | (cd examples/hello_world && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh) + - | + (cd examples/hello_world/chrome && ./build.sh) - | (cd examples/smorgasboard && sed -i 's/: "webpack-dev-server"/: "webpack"/' package.json && ./build.sh) diff --git a/examples/hello_world/README.md b/examples/hello_world/README.md index 6c154cc3..02abbba5 100644 --- a/examples/hello_world/README.md +++ b/examples/hello_world/README.md @@ -13,6 +13,33 @@ $ ./build.sh and then opening up `index.html` in a web browser should show a dialog! -In Chrome, you'll need to delete hello_world_wasm.wasm after building (or -change hello_world.js to import hello_world_wasm.js instead) and uncomment the -relevant line in index.js to work around a webpack bug. +## Caveat for Chrome users + +Note that unfortunately this example does not yet work in Chrome. Chrome has +different limits than than Firefox, for example, about instantiating wasm +modules. Currently the Webpack wasm integration uses `new WebAssembly.Instance` +which limits the input module to at most 4K, but frequently (especially in +development mode) wasm modules may be larger than 4K. + +The usage of `new WebAssembly.Instance` is currently believed to [be a bug][bug] +in webpack which is likely to get fixed once [`instantiateStreaming`][bug2] is +used instead. Once this is fixed in upstream Webpack then this example with work +in Chrome (like it does currently in Firefox). + +In the meantime, however, there's a `chrome` directory in this folder which also +has a `build.sh` script that contains a workaround for this issue. If you're +using chrome it's recommended to `cd` into that folder and run that script. + +The workaround here is a `wasm2es6js` tool, which is currently a bit of a hack. +The wasm-bindgen project assumes that wasm files are ES6 modules (as does +Webpack's current integration), so the `wasm2es6js` translates a wasm file to a +JS file by explicitly instantiating the wasm module rather than relying on the +bundler to do it. When doing this we can manually use +`WebAssemblyly.instantiate` which does not have similar limits in Chrome. + +If all this seems unfortunate for now, don't worry because it should hopefully +be fixed soon! If you've got any questions about this though feel free to ask on +the issue tracker or in the `#rust-wasm` IRC channel. + +[bug]: https://github.com/webpack/webpack/issues/6475 +[bug2]: https://github.com/webpack/webpack/issues/6433 diff --git a/examples/hello_world/build.sh b/examples/hello_world/build.sh index 60bd980b..770873c5 100755 --- a/examples/hello_world/build.sh +++ b/examples/hello_world/build.sh @@ -15,16 +15,6 @@ cargo +nightly run --manifest-path ../../crates/wasm-bindgen-cli/Cargo.toml \ ../../target/wasm32-unknown-unknown/release/hello_world.wasm --out-dir . # wasm-bindgen ../../target/wasm32-unknown-unknown/hello_world.wasm --out-dir . -# To avoid a bug occurring when webpack, wasm, and Chrome are used together, we -# convert the .wasm module to a .js module that embeds the wasm bytecode. To -# enable this, delete hello_world_wasm.wasm after building or change -# hello_world.js to import from hello_world_wasm.js explicitly and uncomment -# the relevant line in index.js. -cargo +nightly run --manifest-path ../../crates/wasm-bindgen-cli/Cargo.toml \ - --bin wasm2es6js -- \ - --base64 -o hello_world_wasm.js hello_world_wasm.wasm -# wasm2es6js --base64 -o hello_world_wasm.js hello_world_wasm.wasm - # Finally, package everything up using Webpack and start a server so we can # browse the result npm install diff --git a/examples/hello_world/chrome/build.sh b/examples/hello_world/chrome/build.sh new file mode 100755 index 00000000..1190f973 --- /dev/null +++ b/examples/hello_world/chrome/build.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +set -ex + +# This is the same as the directory above this. +cargo +nightly build --target wasm32-unknown-unknown --release +cargo +nightly run -p wasm-bindgen-cli --bin wasm-bindgen -- \ + ../../../target/wasm32-unknown-unknown/release/hello_world.wasm --out-dir . + +# To avoid a bug occurring when webpack, wasm, and Chrome are used together, we +# convert the .wasm module to a .js module that embeds the wasm bytecode. To +# enable this, delete hello_world_wasm.wasm after building or change +# hello_world.js to import from hello_world_wasm.js explicitly and uncomment +# the relevant line in index.js. +cargo +nightly run -p wasm-bindgen-cli --bin wasm2es6js -- \ + --base64 -o hello_world_wasm.js hello_world_wasm.wasm +# wasm2es6js --base64 -o hello_world_wasm.js hello_world_wasm.wasm +rm hello_world_wasm.wasm + +# And like the directory above this, from here it's the same. +npm install +npm run serve diff --git a/examples/hello_world/chrome/index.html b/examples/hello_world/chrome/index.html new file mode 120000 index 00000000..79c5d6f0 --- /dev/null +++ b/examples/hello_world/chrome/index.html @@ -0,0 +1 @@ +../index.html \ No newline at end of file diff --git a/examples/hello_world/chrome/index.js b/examples/hello_world/chrome/index.js new file mode 100644 index 00000000..a5291a92 --- /dev/null +++ b/examples/hello_world/chrome/index.js @@ -0,0 +1,11 @@ +// Note that unlike the directory above this we don't need to use an +// asynchronous `import` statement as we're just working with JS here so we can +// use normal `import { ... }` statements. +// +// Unlike before however we have to *also* import the JS file itself containing +// wasm (generated by wasm2es6js) which has a `booted` promise to let us know +// when it's ready to go. +import { greet } from './hello_world'; +import { booted } from './hello_world_wasm'; + +booted.then(() => greet("World!")); diff --git a/examples/hello_world/chrome/package.json b/examples/hello_world/chrome/package.json new file mode 120000 index 00000000..4e26811d --- /dev/null +++ b/examples/hello_world/chrome/package.json @@ -0,0 +1 @@ +../package.json \ No newline at end of file diff --git a/examples/hello_world/chrome/webpack.config.js b/examples/hello_world/chrome/webpack.config.js new file mode 120000 index 00000000..2882e19e --- /dev/null +++ b/examples/hello_world/chrome/webpack.config.js @@ -0,0 +1 @@ +../webpack.config.js \ No newline at end of file