mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-24 10:11:34 +00:00
Implement the local JS snippets RFC
This commit is an implementation of [RFC 6] which enables crates to inline local JS snippets into the final output artifact of `wasm-bindgen`. This is accompanied with a few minor breaking changes which are intended to be relatively minor in practice: * The `module` attribute disallows paths starting with `./` and `../`. It requires paths starting with `/` to actually exist on the filesystem. * The `--browser` flag no longer emits bundler-compatible code, but rather emits an ES module that can be natively loaded into a browser. Otherwise be sure to check out [the RFC][RFC 6] for more details, and otherwise this should implement at least the MVP version of the RFC! Notably at this time JS snippets with `--nodejs` or `--no-modules` are not supported and will unconditionally generate an error. [RFC 6]: https://github.com/rustwasm/rfcs/pull/6 Closes #1311
This commit is contained in:
@ -27,6 +27,7 @@
|
||||
- [web-sys: A TODO MVC App](./examples/todomvc.md)
|
||||
- [Reference](./reference/index.md)
|
||||
- [Deployment](./reference/deployment.md)
|
||||
- [JS snippets](./reference/js-snippets.md)
|
||||
- [Passing Rust Closures to JS](./reference/passing-rust-closures-to-js.md)
|
||||
- [Receiving JS Closures in Rust](./reference/receiving-js-closures-in-rust.md)
|
||||
- [`Promise`s and `Future`s](./reference/js-promises-and-rust-futures.md)
|
||||
|
@ -4,12 +4,15 @@
|
||||
|
||||
[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/without-a-bundler
|
||||
|
||||
This example shows how the `--no-modules` flag can be used load code in a
|
||||
This example shows how the `--browser` flag can be used load code in a
|
||||
browser directly. For this deployment strategy bundlers like Webpack are not
|
||||
required. For more information on deployment see the [dedicated
|
||||
documentation][deployment].
|
||||
|
||||
First let's take a look at the code and see how when we're using `--no-modules`
|
||||
> **Note**: the `--browser` flag is quite new to `wasm-bindgen`, and does not
|
||||
> currently have support in `wasm-pack` yet. Support will be added soon though!
|
||||
|
||||
First let's take a look at the code and see how when we're using `--browser`
|
||||
we're not actually losing any functionality!
|
||||
|
||||
```rust
|
||||
@ -22,7 +25,33 @@ Otherwise the rest of the deployment magic happens in `index.html`:
|
||||
{{#include ../../../examples/without-a-bundler/index.html}}
|
||||
```
|
||||
|
||||
And that's it! Be sure to read up on the [deployment options][deployment] to see what it
|
||||
means to deploy without a bundler.
|
||||
And that's it! Be sure to read up on the [deployment options][deployment] to see
|
||||
what it means to deploy without a bundler.
|
||||
|
||||
[deployment]: ../reference/deployment.html
|
||||
|
||||
## Using the older `--no-modules`
|
||||
|
||||
[View full source code][code]
|
||||
|
||||
[code]: https://github.com/rustwasm/wasm-bindgen/tree/master/examples/without-a-bundler-no-modules
|
||||
|
||||
The older version of using `wasm-bindgen` without a bundler is to use the
|
||||
`--no-modules` flag to the `wasm-bindgen` CLI. This corresponds to `--target
|
||||
no-modules` in `wasm-pack`.
|
||||
|
||||
While similar to the newer `--browser`, the `--no-modules` flag has a few
|
||||
caveats:
|
||||
|
||||
* It does not support [local JS snippets][snippets]
|
||||
* It does not generate an ES module
|
||||
|
||||
With that in mind the main difference is how the wasm/JS code is loaded, and
|
||||
here's an example of loading the output of `wasm-pack` for the same module as
|
||||
above.
|
||||
|
||||
```html
|
||||
{{#include ../../../examples/without-a-bundler-no-modules/index.html}}
|
||||
```
|
||||
|
||||
[snippets]: ../reference/js-snippets.html
|
||||
|
@ -29,26 +29,29 @@ necessary.
|
||||
|
||||
If you're not using a bundler but you're still running code in a web browser,
|
||||
`wasm-bindgen` still supports this! For this use case you'll want to use the
|
||||
`--no-modules` flag. You can check out a [full example][nomex] in the
|
||||
`--browser` flag. You can check out a [full example][nomex] in the
|
||||
documentation, but the highlights of this output are:
|
||||
|
||||
* When using `wasm-pack` you'll pass `--target no-modules`, and when using
|
||||
`wasm-bindgen` directly you'll pass `--no-modules`.
|
||||
* When using `wasm-bindgen` directly you'll pass `--browser`.
|
||||
* The output can natively be included on a web page, and doesn't require any
|
||||
further postprocessing.
|
||||
* The `--no-modules` mode is not able to use NPM dependencies nor local JS
|
||||
snippets (both currently [proposed][rfc1] [features][rfc2])
|
||||
further postprocessing. The output is included as an ES module.
|
||||
* The `--browser` mode is not able to use NPM dependencies.
|
||||
* You'll want to review the [browser requirements] for `wasm-bindgen` because
|
||||
no polyfills will be available.
|
||||
|
||||
> **Note**: currently `--browser` is not supported in `wasm-pack` because it is
|
||||
> a very recent addition to `wasm-bindgen`, but support will be added soon!
|
||||
|
||||
[nomex]: ../examples/without-a-bundler.html
|
||||
[rfc1]: https://github.com/rustwasm/rfcs/pull/6
|
||||
[rfc2]: https://github.com/rustwasm/rfcs/pull/8
|
||||
[browser requirements]: browser-support.html
|
||||
|
||||
Despite these limitations almost all code today is compatible with
|
||||
`--no-modules`, but this area is actively being worked on to improve the
|
||||
experience so the experience here may be tweaked over time!
|
||||
The `wasm-bindgen` CLI also supports an output mode called `--no-modules` which
|
||||
is similar to `--browser` in that it requires manual initialization of the wasm
|
||||
and is intended to be included in web pages without any further postprocessing.
|
||||
See the [without a bundler example][nomex] for some more information about
|
||||
`--no-modules`, which corresponds to `--target no-modules` in `wasm-pack`.
|
||||
|
||||
## Node.js
|
||||
|
||||
|
78
guide/src/reference/js-snippets.md
Normal file
78
guide/src/reference/js-snippets.md
Normal file
@ -0,0 +1,78 @@
|
||||
# JS Snippets
|
||||
|
||||
Often when developing a crate you want to run on the web you'll want to include
|
||||
some JS code here and there. While [`js-sys`](https://docs.rs/js-sys) and
|
||||
[`web-sys`](https://docs.rs/web-sys) cover many needs they don't cover
|
||||
everything, so `wasm-bindgen` supports the ability to write JS code next to your
|
||||
Rust code and have it included in the final output artifact.
|
||||
|
||||
To include a local JS file, you'll use the `#[wasm_bindgen(module)]` macro:
|
||||
|
||||
```rust
|
||||
#[wasm_bindgen(module = "/js/foo.js")]
|
||||
extern "C" {
|
||||
fn add(a: u32, b: u32) -> u32;
|
||||
}
|
||||
```
|
||||
|
||||
This declaration indicates that all the functions contained in the `extern`
|
||||
block are imported from the file `/js/foo.js`, where the root is relative to the
|
||||
crate root (where `Cargo.toml` is located).
|
||||
|
||||
The `/js/foo.js` file will make its way to the final output when `wasm-bindgen`
|
||||
executes, so you can use the `module` annotation in a library without having to
|
||||
worry users of your library!
|
||||
|
||||
The JS file itself must be written with ES module syntax:
|
||||
|
||||
```js
|
||||
export function add(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
```
|
||||
|
||||
A full design of this feature can be found in [RFC 6] as well if you're
|
||||
interested!
|
||||
|
||||
[RFC 6]: https://github.com/rustwasm/rfcs/pull/6
|
||||
|
||||
### Using `inline_js`
|
||||
|
||||
In addition to `module = "..."` if you're a macro author you also have the
|
||||
ability to use the `inline_js` attribute:
|
||||
|
||||
```rust
|
||||
#[wasm_bindgen(inline_js = "export function add(a, b) { return a + b; }")]
|
||||
extern "C" {
|
||||
fn add(a: u32, b: u32) -> u32;
|
||||
}
|
||||
```
|
||||
|
||||
Using `inline_js` indicates that the JS module is specified inline in the
|
||||
attribute itself, and no files are loaded from the filesystem. They have the
|
||||
same limitations and caveats as when using `module`, but can sometimes be easier
|
||||
to generate for macros themselves. It's not recommended for hand-written code to
|
||||
make use of `inline_js` but instead to leverage `module` where possible.
|
||||
|
||||
### Caveats
|
||||
|
||||
While quite useful local JS snippets currently suffer from a few caveats which
|
||||
are important to be aware of. Many of these are temporary though!
|
||||
|
||||
* Currently `import` statements are not supported in the JS file. This is a
|
||||
restriction we may lift in the future once we settle on a good way to support
|
||||
this. For now, though, js snippets must be standalone modules and can't import
|
||||
from anything else.
|
||||
|
||||
* Only `--browser` and the default bundler output mode are supported. To support
|
||||
`--nodejs` we'd need to translate ES module syntax to CommonJS (this is
|
||||
planned to be done, just hasn't been done yet). Additionally to support
|
||||
`--no-modules` we'd have to similarly translate from ES modules to something
|
||||
else.
|
||||
|
||||
* Paths in `module = "..."` must currently start with `/`, or be rooted at the
|
||||
crate root. It is intended to eventually support relative paths like `./` and
|
||||
`../`, but it's currently believed that this requires more support in
|
||||
the Rust `proc_macro` crate.
|
||||
|
||||
As above, more detail about caveats can be found in [RFC 6].
|
Reference in New Issue
Block a user