diff --git a/README.md b/README.md index 53af817e..11ed9c36 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,10 @@ This tool seeks to be a one-stop shop for building and working with rust- generated WebAssembly that you would like to interop with JavaScript, in the -browser or with Node.js. `wasm-pack` helps you build and publish rust-generated -WebAssembly to the npm registry to be used alongside any other javascript -package in workflows that you already use, such as [webpack] or [greenkeeper]. +browser or with Node.js. `wasm-pack` helps you build rust-generated +WebAssembly packages that you could publish to the npm registry, or otherwise use +alongside any javascript packages in workflows that you already use, such as [webpack] +or [greenkeeper]. [bundler-support]: https://github.com/rustwasm/team/blob/master/goals/bundler-integration.md#details [webpack]: https://webpack.js.org/ diff --git a/docs/index.html b/docs/index.html index 2566c104..7ed3c4bd 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,6 +2,7 @@ wasm-pack + @@ -51,6 +52,60 @@

📦✨ your favorite rust -> wasm workflow tool!

+
+
+
+

Build it with wasm-pack!

+
+
+
+ webpack +

Hybrid Applications with Webpack

+
+

+ Develop a WebAssembly module alongside any JavaScript project + that leverages Webpack. + Edit your Rust and watch your WebAssembly compile and reload as + you work- a great way to start exploring WebAssembly in a JavaScript + application you already work on! +

+ Learn More +
+
+
+ npm packages +

npm Packages for the Broswer and Node.js

+
+

+ Leverage the power and breadth of the Rust ecosystem by compiling + and publishing packages from crates.io + as WebAssembly packages to the npm Registry + - or write your own! Surgically replace hotpaths in your JavaScript or + Node.js application with WebAssembly modules- using the same tools you + use for your JavaScript dependencies! +

+ Learn More +
+
+
+ webpack +

Standalone WASM binaries

+
+

+ No registry?
No bundler?
No problem!
+

+

+ wasm-pack plays well with others but is also happy to generate + standalone binaries for consumption in the browser. +

+ Learn More +
+
+
+
+ diff --git a/docs/public/custom.css b/docs/public/custom.css index 847d1b85..4a1705f8 100644 --- a/docs/public/custom.css +++ b/docs/public/custom.css @@ -24,6 +24,7 @@ position: relative; float: left; margin-bottom: 0; + bottom: -5px; } .navbar-logo a img { @@ -96,3 +97,48 @@ a { color: #6556EC; } + +img { + width: 100%; +} + +.button { + display: block; +} + +div header { + min-height: 270px; + font-weight: 400; +} + +footer { + background-color: #6556EC; + color: white; + margin: 50px 0 0 0; + padding: 20px 0 5px; + text-align: center; +} + +footer a { + color: white; +} + +@media only screen and (min-width: 800px) { + #build .columns { + position: relative; + min-height: 550px; + } + + #build a.button { + width: 100%; + position: absolute; + bottom: 0; + } +} + +@media only screen and (max-width: 800px) { + #build .columns { + padding: 40px 0; + border-top: solid rgb(187, 187, 187) 1px; + } +} diff --git a/docs/public/img/npm-packages.png b/docs/public/img/npm-packages.png new file mode 100644 index 00000000..fe1fe9b9 Binary files /dev/null and b/docs/public/img/npm-packages.png differ diff --git a/docs/public/img/wasmbinaries.png b/docs/public/img/wasmbinaries.png new file mode 100644 index 00000000..64a967d0 Binary files /dev/null and b/docs/public/img/wasmbinaries.png differ diff --git a/docs/public/img/webpack.jpeg b/docs/public/img/webpack.jpeg new file mode 100644 index 00000000..8a0faf33 Binary files /dev/null and b/docs/public/img/webpack.jpeg differ diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 25e2e4fa..99ec5b89 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -3,21 +3,31 @@ - [Prerequisites](./prerequisites/index.md) - [Rust](./prerequisites/rust.md) - [npm](./prerequisites/npm.md) -- [Project Setup](./project-setup/index.md) - - [Using a Template](./project-setup/using-a-template.md) - - [Manual Setup](./project-setup/manual-setup.md) - [Commands](./commands/index.md) - [`init` (DEPRECATED)](./commands/init.md) - [`build`](./commands/build.md) - [`pack` and `publish`](./commands/pack-and-publish.md) -- [Tutorial](./tutorial/index.md) - - [Getting Started](./tutorial/getting-started.md) - - [Template Deep Dive](./tutorial/template-deep-dive/index.md) - - [`Cargo.toml`](./tutorial/template-deep-dive/cargo-toml.md) - - [`src/lib.rs`](./tutorial/template-deep-dive/src-lib-rs.md) - - [`src/utils.rs`](./tutorial/template-deep-dive/src-utils-rs.md) - - [`wee_alloc`](./tutorial/template-deep-dive/wee_alloc.md) - - [Packaging and Publishing](./tutorial/packaging-and-publishing.md) - - [Using your Library](./tutorial/using-your-library.md) +- [Tutorials](./tutorials/index.md) + - [Hybrid applications with Webpack](./tutorials/hybrid-applications-with-webpack/index.md) + - [Getting started](./tutorials/hybrid-applications-with-webpack/getting-started.md) + - [Template deep dive](./tutorials/hybrid-applications-with-webpack/template-deep-dive/index.md) + - [`Cargo.toml`](./tutorials/hybrid-applications-with-webpack/template-deep-dive/cargo-toml.md) + - [`src/lib.rs`](./tutorials/hybrid-applications-with-webpack/template-deep-dive/src-lib-rs.md) + - [Building your project](./tutorials/hybrid-applications-with-webpack/template-deep-dive/building-your-project.md) + - [Using your library](./tutorials/hybrid-applications-with-webpack/using-your-library.md) + - [npm browser packages](./tutorials/npm-browser-packages/index.md) + - [Getting started](./tutorials/npm-browser-packages/getting-started.md) + - [Project setup](./tutorials/npm-browser-packages/project-setup/index.md) + - [Using a Template](./tutorials/npm-browser-packages/project-setup/using-a-template.md) + - [Manual Setup](./tutorials/npm-browser-packages/project-setup/manual-setup.md) + - [Template deep dive](./tutorials/npm-browser-packages/template-deep-dive/index.md) + - [`Cargo.toml`](./tutorials/npm-browser-packages/template-deep-dive/cargo-toml.md) + - [`src/lib.rs`](./tutorials/npm-browser-packages/template-deep-dive/src-lib-rs.md) + - [`src/utils.rs`](./tutorials/npm-browser-packages/template-deep-dive/src-utils-rs.md) + - [`wee_alloc`](./tutorial/template-deep-dive/wee_alloc.md) + - [Building your project](./tutorials/npm-browser-packages/template-deep-dive/building-your-project.md) + - [Packaging and publishing](./tutorials/npm-browser-packages/packaging-and-publishing.md) + - [Using your library](./tutorials/npm-browser-packages/using-your-library.md) + - [Standalone WASM binaries](./tutorials/standalone-wasm-binaries/index.md) - [`Cargo.toml` Configuration](./cargo-toml-configuration.md) - [Contributing](./contributing.md) diff --git a/docs/src/command/pack-and-publish.md b/docs/src/command/pack-and-publish.md deleted file mode 100644 index 181e2749..00000000 --- a/docs/src/command/pack-and-publish.md +++ /dev/null @@ -1 +0,0 @@ -# pack and publish diff --git a/docs/src/tutorials/hybrid-applications-with-webpack/getting-started.md b/docs/src/tutorials/hybrid-applications-with-webpack/getting-started.md new file mode 100644 index 00000000..da1c528d --- /dev/null +++ b/docs/src/tutorials/hybrid-applications-with-webpack/getting-started.md @@ -0,0 +1,15 @@ +# Getting Started + +You can create a new Rust-WebAssembly webpack project by using the [rustwasm webpack-template]. + +Run: + +``` +npm init rust-webpack my-app +``` + +The last argument will be your project name. After you run the command, you will have a +directory with a new project, ready to go. We'll talk about what's been included in this +template further in this guide. + +[rustwasm webpack-template]: https://github.com/rustwasm/rust-webpack-template diff --git a/docs/src/tutorials/hybrid-applications-with-webpack/index.md b/docs/src/tutorials/hybrid-applications-with-webpack/index.md new file mode 100644 index 00000000..fed22d83 --- /dev/null +++ b/docs/src/tutorials/hybrid-applications-with-webpack/index.md @@ -0,0 +1,21 @@ +# Hybrid Applications with Webpack + +The goal of this tutorial is to introduce you to the `rust-webpack-template` +and the `wasm-pack` workflow by building the example app in the template. + +This tutorial is aimed at folks who are both beginners to WebAssembly and Rust- you don't need +much Rust knowledge to complete this tutorial. + +Be sure to have done the following before starting: + +1. [Install `wasm-pack`](../../installer) +1. Read and install the [Prerequisites](../prerequisites/index.html). + + - You'll need [Rust], version 1.30 or higher. (Currently either `beta` or `nightly` channels). [Learn more](../project-setup/rust.html). + - You'll need [Node.js] and [npm] installed. [Learn more](../project-setup/npm.html). + +⚠️ We strongly recommend that you install [Node.js] using a version manager. You can learn more [here](https://npmjs.com/get-npm). + +[Rust]: https://www.rust-lang.org +[Node.js]: https://nodejs.org +[npm]: https://npmjs.com diff --git a/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/building-your-project.md b/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/building-your-project.md new file mode 100644 index 00000000..a8aef61c --- /dev/null +++ b/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/building-your-project.md @@ -0,0 +1,23 @@ +# Building your project + +We are writing a package that should be used in the browser, so we run this in our terminal: + +```bash +$ wasm-pack build +``` + +If you were writing a package that should be used in Node.js (with CommonJS modules, e.g. `require`), +you would run this in your terminal: + +```bash +$ wasm-pack build --target nodejs +``` + +This command does a few things when run: + +1. It'll compile your code to wasm if you haven't already +2. It'll generate a `pkg` folder. Inside there will be: + - a Rust-compiled to wasm file + - a JavaScript wrapper file around the wasm + - TypeScript declaration files to convey information about types + - a `package.json` file diff --git a/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/cargo-toml.md b/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/cargo-toml.md new file mode 100644 index 00000000..c79ae2c4 --- /dev/null +++ b/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/cargo-toml.md @@ -0,0 +1,123 @@ +# Cargo.toml + +We'll see more about how to use this library when we discuss what has been generated in `lib.rs`. + +`Cargo.toml` is the manifest file for Rust's package manager, `cargo`. This file contains +metadata such as name, version, and dependencies for packages, which are call "crates" in Rust. + +There's a bunch of metadata that the template gives us, but there are 4 key parts to discuss: + +- [`crate-type`](#a1-crate-type) +- [`wasm-bindgen` dependency](#a2-wasm-bindgen-dependency) +- [`[features]` and `wee-alloc`, `console-error-panic-hook` dependencies](#a3-features-and-wee-alloc-console-error-panic-hook-dependencies) +- [`web-sys` dependency](#a4-web-sys-dependency) + +
+ +## 1. `crate-type` + +```toml +[lib] +crate-type = ["cdylib"] +``` + +A Rust-`wasm` crate is a bit different from a normal crate, and as a result, we need to note +this in our `Cargo.toml`. + +When `cargo` is told to build a project, or compilation is otherwise done on a Rust project, +the Rust compiler will need to link crates together, using a particular method, either +statically or dynamically. The two types of crate that you are likely most familiar with are +`#[crate_type = "bin"]` and `#[crate_type = "lib"]`, which are the crate types that largely +represent the difference between Rust application projects and Rust libraries. + +`#[crate_type = "cdylib"]` signifies that you'd like the compiler to create a dynamic system +library. This type of library is suited for situations where you'd like to compile Rust code +as a dynamic library to be loaded from another language. In our case, we'll be compiling to a +`*.wasm` file, but this output type will create `*.so` files on Linux, `*.dylib` files on +macOS, and `*.dll` files on Windows in non-`wasm` circumstances. + +You can read more about linking and crate types, [here](https://doc.rust-lang.org/reference/linkage.html). + +## 2. `wasm-bindgen` dependency + +`wasm-bindgen` is our most important dependency. This package allows us to use the +`#[wasm-bindgen]` attribute to tag code that represents the interface we want between +our JavaScript and Rust-generated `wasm`. We can import JS and export Rust by using this +attribute. + +```toml +wasm-bindgen = "0.2" +``` + +We'll see more about how to use this library when we discuss what has been generated in `lib.rs`. + +⚠️ If you are coming from JavaScript, you might note that when we add the dependency +there is no `^` or `~` symbol- it looks like we're locking to the `0.2` version. +However, that's not the case! In Rust, the `^` is implied. + +## 3. `[features]` and `wee-alloc`, `console-error-panic-hook` dependencies + +As part of our effort to design a template that helps people discover useful crates +for their particular use case, this template includes 2 dependencies that can be +very useful for folks developing Rust-`wasm` crates: `console-error-panic-hook` and +`wee-alloc`. + +Because these dependencies are useful primarily in a specific portion of the Rust-`wasm` +crate development workflow, we've also set up a bit of glue code that allows us to include +them both as dependences, but allowing for them to be optionally included. + +```toml +[features] +default-features = ["console_error_panic_hook"] + +[dependencies] +cfg-if = "0.1.5" + +# The `console_error_panic_hook` crate provides better debugging of panics by +# logging them with `console.error`. This is great for development, but requires +# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for +# code size when deploying. +console_error_panic_hook = { version = "0.1.1", optional = true } + +# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size +# compared to the default allocator's ~10K. It is slower than the default +# allocator, however. +wee_alloc = { version = "0.4.2", optional = true } +``` + +[`cfg-if`] allows us to check if certain features are enabled on a Rust crate. We'll +use this crate in `lib.rs` to optionally enable `console_error_panic_hook` or +`wee_alloc`. By default, we have `console_error_panic_hook` enabled. +To disable features, we can remove their entry from the `default-features` vector. + +To learn more about these features, we discuss them in depth in the `lib.rs` section. + +Briefly, they include: + ++ **console_error_panic_hook** for logging panic messages to the developer console. ++ **wee_alloc**, an allocator optimized for small code size. + +## 4. `web-sys` dependency + +The [`web-sys` crate](https://crates.io/crates/web-sys) provides raw wasm-bindgen imports for all of the Web's APIs. +In our `Cargo.toml` file, we list the APIs we want to use from `web-sys` in +order to have them compiled. This crate by default contains very little +when compiled as almost all of its exposed APIs are gated by Cargo features. +Below we see the features that are pulled in by generated Cargo.toml +from the rust-webpack template. + +```toml +[dependencies.web-sys] +version = "0.3" +features = [ + "Document", + "Element", + "HtmlElement", + "Node", + "Window", +] +``` + +You can see the exhaustive list of features in `crates/web-sys/Cargo.toml` +and enable them by looking at the [documentation](https://rustwasm.github.io/wasm-bindgen/api/web_sys/) +to see what features they depend on. diff --git a/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/index.md b/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/index.md new file mode 100644 index 00000000..ed445a84 --- /dev/null +++ b/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/index.md @@ -0,0 +1,15 @@ +# Template Deep Dive + +⚠️ This section is a deep dive into the contents of the rust-wasm webpack template project, +specifically written for people who are not that familiar with Rust. If you'd rather just +checkout the workflow, feel free to skip this section! + +⚠️ If you haven't used a template to set up your project, the contents of your files +may look slightly different than what is described here. + +### What the Template Gave Us + +Let's start by taking a look at what the template generated for us. + +- [`Cargo.toml`](./cargo-toml.html) +- [`src/lib.rs`](./src-lib-rs.html) diff --git a/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/src-lib-rs.md b/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/src-lib-rs.md new file mode 100644 index 00000000..9e79b3d6 --- /dev/null +++ b/docs/src/tutorials/hybrid-applications-with-webpack/template-deep-dive/src-lib-rs.md @@ -0,0 +1,306 @@ +# src/lib.rs + +`lib.rs` is the template's main source file. In the +rust-webpack template, the `lib.rs` is generated inside the +`crate` directory. Libraries in Rust are commonly called +crates and for this template, the Rust code written in this +file will be compiled as a library. + +Our project contains four key parts: + +- [`#[wasm_bindgen] functions`](#a1-wasm_bindgen-functions) +- [Crate imports](#a2-crate-imports) +- [`wee_alloc` optional dependency](#a3-wee_alloc-optional-dependency) + - [What is `wee_alloc`?](#what-is-wee_alloc) +- [Defining `set_panic_hook`](#a4-defining-set_panic_hook) +- [`web-sys` features](#a5-web-sys-features) + +--- + +We'll start with the most important part of this `lib.rs` +file -- the `#[wasm_bindgen]` functions. In the rust-webpack +template, `lib.rs` will be the only place you need to modify +and add Rust code. + +## 1. `#[wasm_bindgen]` functions + +The `#[wasm_bindgen]` attribute indicates that the function +below it will be accessible both in JavaScript and Rust. + +```rust +// Called by our JS entry point to run the example. +#[wasm_bindgen] +pub fn run() -> Result<(), JsValue> { + // ... + Ok(()) +} +``` + +If we were to write the `run` function without the +`#[wasm_bindgen]` attribute, then `run` would not be easily +accessible within JavaScript. Furthermore, we wouldn't be +able to natively convert certain types such as `()` between +JavaScript and Rust. So, the `#[wasm_bindgen]` attribute +allows `run` to be called from JavaScript. + +This is all you need to know to interface with JavaScript! +If you are curious about the rest, read on. + +## 2. Crate imports + +```rust +#[macro_use] +extern crate cfg_if; +extern crate web_sys; +extern crate wasm_bindgen; +``` + +In `Cargo.toml`, we included the crates `cfg_if`, `web_sys`, +and `wasm_bindgen` as project dependencies. + +Here, we explicitly declare that these crates will be used +in `lib.rs`. + +```rust +use wasm_bindgen::prelude::*; +``` + +`use` allows us to conveniently refer to parts of a crate or +module. For example, suppose the crate `wasm_bindgen` +contains a function `func`. It is always possible to call +this function directly by writing `wasm_bindgen::func()`. +However, this is often tedious to write. If we first specify +`use wasm_bindgen::func;`, then `func` can be called by just +writing `func()` instead. + +In our `use` statement above we further specify a `prelude` +module. Many modules contain a "prelude", a list of things +that should be automatically imported. This allows common +features of the module to be conveniently accessed without a +lengthy prefix. For example, in this file we can use +`#[wasm_bindgen]` only because it is brought into scope by +the prelude. + +The asterisk at the end of this `use` indicates that +everything inside the module `wasm_bindgen::prelude` (i.e. +the module `prelude` inside the crate `wasm_bindgen`) can be +referred to without prefixing it with +`wasm_bindgen::prelude`. + +For example, `#[wasm_bindgen]` could also be written as +`#[wasm_bindgen::prelude::wasm_bindgen]`, although this is +not recommended. + +One other point of interest is how we import the `cfg_if!` +macro. + +```rust +#[macro_use] +extern crate cfg_if; +``` + +The `#[macro_use]` attribute imports the `cfg_if!` macro the +same way a `use` statement imports functions. + + +## 3. `wee_alloc` optional dependency + +```rust +cfg_if! { + // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global + // allocator. + if #[cfg(feature = "wee_alloc")] { + extern crate wee_alloc; + #[global_allocator] + static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + } +} +``` + +This code block is intended to initialize `wee_alloc` as the +global memory allocator, but only if the `wee_alloc` feature +is enabled in `Cargo.toml`. + +We immediately notice that `cfg_if!` is a macro because it +ends in `!`, similarly to other Rust macros such as +`println!` and `vec!`. A macro is directly replaced by other +code during compile time. + +During compile time, `cfg_if!` evaluates the `if` statement. +This tests whether the feature `wee_alloc` is present in the +`[features]` section of `Cargo.toml` (among other possible +ways to set it). + +As we saw earlier, the `default` vector in `[features]` only +contains `"console_error_panic_hook"` and not `"wee_alloc"`. +So, in this case, the `cfg_if!` block will be replaced by no +code at all, and hence the default memory allocator will be +used instead of `wee_alloc`. + +```rust +extern crate wee_alloc; +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; +``` + +However, suppose `"wee_alloc"` is appended to the `default` +vector in `Cargo.toml`. Then, the `cfg_if!` block is instead +replaced with the contents of the `if` block, shown above. + +This code sets the `wee_alloc` allocator to be used as the +global memory allocator. + +### What is `wee_alloc`? + +Reducing the size of compiled WebAssembly code is important, +since it is often transmitted over the Internet or placed on +embedded devices. + +> `wee_alloc` is a tiny allocator designed for WebAssembly +> that has a (pre-compression) code-size footprint of only a +> single kilobyte. + +[An analysis](http://fitzgeraldnick.com/2018/02/09/wee-alloc.html) +suggests that over half of the bare minimum WebAssembly +memory footprint is required by Rust's default memory +allocator. Yet, WebAssembly code often does not require a +sophisticated allocator, since it often just requests a +couple of large initial allocations. + +`wee_alloc` trades off size for speed. Although it has a +tiny code-size footprint, it is relatively slow if +additional allocations are needed. + +For more details, see the +[`wee_alloc` repository](https://github.com/rustwasm/wee_alloc). + +## 4. Defining `set_panic_hook` + +```rust +cfg_if! { + // When the `console_error_panic_hook` feature is enabled, we can call the + // `set_panic_hook` function to get better error messages if we ever panic. + if #[cfg(feature = "console_error_panic_hook")] { + extern crate console_error_panic_hook; + use console_error_panic_hook::set_once as set_panic_hook; + } else { + #[inline] + fn set_panic_hook() {} + } +} +``` + +As described in the `wee_alloc` section, the macro `cfg_if!` +evaluates the `if` statement during compile time. This is +possible because it is essentially testing whether +`"console_error_panic_hook"` is defined in the `[features]` +section of `Cargo.toml`, which is available during compile +time. + +The entire macro block will either be replaced with the +statements in the `if` block or with those in the `else` +block. These two cases are now described in turn: + +```rust +extern crate console_error_panic_hook; +use console_error_panic_hook::set_once as set_panic_hook; +``` + +Due to the `use` statement, the function +`console_error_panic_hook::set_once` can now be +accessed more conveniently as `set_panic_hook`. + +```rust +#[inline] +fn set_panic_hook() {} +``` + +An inline function replaces the function call with the +contents of the function during compile time. Here, +`set_panic_hook` is defined to be an empty inline function. +This allows the use of `set_panic_hook` without any run-time +or code-size performance penalty if the feature is not +enabled. + +### What is `console_error_panic_hook`? + +The crate `console_error_panic_hook` enhances error messages +in the web browser. This allows you to easily debug +WebAssembly code. + +Let's compare error messages before and after enabling the +feature: + +**Before:** `"RuntimeError: Unreachable executed"` + +**After:** `"panicked at 'index out of bounds: the len is 3 +but the index is 4', libcore/slice/mod.rs:2046:10"` + +To do this, a panic hook for WebAssembly is provided that +logs panics to the developer console via the JavaScript +`console.error` function. + +Note that although the template sets up the function, your +error messages will not automatically be enhanced. To enable +the enhanced errors, call the function `set_panic_hook()` in +`lib.rs` when your code first runs. The function may be +called multiple times if needed. + +For more details, see the +[`console_error_panic_hook` repository](https://github.com/rustwasm/console_error_panic_hook). + +## 5. `web-sys` features + +The `web-sys` crate enables us to access elements in web +browsers. + +By looking at the generated code, we can see we're using a +few of the elements provided by the API in the `web-sys` +crate. + +```rust +pub fn run() -> Result<(), JsValue> { + set_panic_hook(); + + let window = web_sys::window().expect("should have a Window"); + let document = window.document().expect("should have a Document"); + + let p: web_sys::Node = document.create_element("p")?.into(); + p.set_text_content(Some("Hello from Rust, WebAssembly, and Webpack!")); + + let body = document.body().expect("should have a body"); + let body: &web_sys::Node = body.as_ref(); + body.append_child(&p)?; + + Ok(()) +} +``` + +Here we're accessing the window of the web browser and +elements inside the document that allow us to put text +inside the web browser when we run this example. + +When this code is run and we look at the output in our web +browser, we are greeted with text in a `p` element in the +body of the document that says ``"Hello from Rust, +WebAssembly, and Webpack!"`` + +In the `Cargo.toml`, we enable the specific features we want +to use by listing them in the features array. Our generated +`Cargo.toml` from the rust-webpack template gives us: +```toml +[dependencies.web-sys] +version = "0.3" +features = [ + "Document", + "Element", + "HtmlElement", + "Node", + "Window", +] +``` + +You can include more features to access more bindings to the +web that the browser provides. You can learn more about +what the `web-sys` crate has to offer +[here](https://rustwasm.github.io/wasm-bindgen/api/web_sys/). diff --git a/docs/src/tutorials/hybrid-applications-with-webpack/using-your-library.md b/docs/src/tutorials/hybrid-applications-with-webpack/using-your-library.md new file mode 100644 index 00000000..f182f6db --- /dev/null +++ b/docs/src/tutorials/hybrid-applications-with-webpack/using-your-library.md @@ -0,0 +1,85 @@ +# Run The Code + +The Rust Webpack template is designed for creating monorepo-style Web applications with +Rust-generated WebAssembly and Webpack without publishing your wasm to NPM. +This portion of the tutorial will explain how to build a [Webpack] JavaScript project +that will run your WebAssembly code in the browser. + +[Webpack]: https://webpack.js.org/ + +## Scaffold a JavaScript Project + +To generate a new Rust Webpack project, we've used the [`rust-webpack`] npm template. + +[`rust-webpack`]: https://github.com/rustwasm/rust-webpack-template + +``` +npm init rust-webpack your-package-name +``` + +A new project folder will be created with the name you supply. + +If we look in the project, we'll see the following: + +- `.gitignore`: ignores `node_modules` +- `LICENSE-APACHE` and `LICENSE-MIT`: most Rust projects are licensed this way, so these are included for you +- `README.md`: the file you are reading now! +- `index.html`: a bare bones html document that includes the webpack bundle +- `js/index.js`: example JS file with a comment showing how to import and use a wasm pkg +- `package.json` and `package-lock.json`: + - pulls in devDependencies for using webpack: + - [`webpack`](https://www.npmjs.com/package/webpack) + - [`webpack-cli`](https://www.npmjs.com/package/webpack-cli) + - [`webpack-dev-server`](https://www.npmjs.com/package/webpack-dev-server) + - defines a `start` script to run `webpack-dev-server` +- `webpack.config.js`: configuration file for bundling your JS with webpack +- `crate/src/lib.rs`: your Rust crate code! + +## Your Rust Crate + +The scaffolded project includes an example Rust WebAssembly webpack crate. + +Inside the `crate/src/lib.rs` file we see a `run` function that's callable from our JS file: +```rust +// Called by our JS entry point to run the example. +#[wasm_bindgen] +pub fn run() -> Result<(), JsValue> { + set_panic_hook(); + + // ... + let p: web_sys::Node = document.create_element("p")?.into(); + p.set_text_content(Some("Hello from Rust, WebAssembly, and Webpack!")); + // ... + + Ok(()) +} +``` + +Now, open up the `js/index.js` file. We see our Rust-generated wasm `run` function being +called inside our JS file. + +```js +import("../crate/pkg").then(module => { + module.run(); +}); +``` + +## Run The Project + +To generate our Rust-compiled to wasm code, in the root directory we run: +```bash +npm run build +``` +This will create our bundled JavaScript module in a new directory `dist`. + +We should be ready to run our project now! +In the root directory, we'll run: + +```bash +npm start +``` + +Then in a web browser navigate to `http://localhost:8080` and you should be greeted +with text in the body of the page that says "Hello from Rust, WebAssembly, and Webpack!" + +If you did congrats! You've successfully used the rust-webpack template! diff --git a/docs/src/tutorials/index.md b/docs/src/tutorials/index.md new file mode 100644 index 00000000..81c8590f --- /dev/null +++ b/docs/src/tutorials/index.md @@ -0,0 +1 @@ +# Tutorials diff --git a/docs/src/tutorials/npm-browser-packages/building-your-package.md b/docs/src/tutorials/npm-browser-packages/building-your-package.md new file mode 100644 index 00000000..7961a04c --- /dev/null +++ b/docs/src/tutorials/npm-browser-packages/building-your-package.md @@ -0,0 +1,24 @@ +# Building your package + +We've written our code so now we need to package it all up. + +We are writing a package that should be used in the browser, so we run this in our terminal: + +```bash +$ wasm-pack build --scope MYSCOPE +``` + +If you were writing a package that should be used in Node.js (with CommonJS modules, e.g. `require`), +you would run this in your terminal: + +```bash +$ wasm-pack build --scope MYSCOPE --target nodejs +``` + +where `MYSCOPE` is your npm username. Normally you could just type `wasm-pack init` but since +other people are doing this tutorial as well we don't want conflicts with the `wasm-add` package +name! This command when run does a few things: + +1. It'll compile your code to wasm if you haven't already +2. It'll generate a pkg folder with the wasm file, a JS wrapper file around the wasm, your README, + and a `package.json` file. diff --git a/docs/src/tutorial/getting-started.md b/docs/src/tutorials/npm-browser-packages/getting-started.md similarity index 100% rename from docs/src/tutorial/getting-started.md rename to docs/src/tutorials/npm-browser-packages/getting-started.md diff --git a/docs/src/tutorial/index.md b/docs/src/tutorials/npm-browser-packages/index.md similarity index 87% rename from docs/src/tutorial/index.md rename to docs/src/tutorials/npm-browser-packages/index.md index 75637ee2..4bd69ca9 100644 --- a/docs/src/tutorial/index.md +++ b/docs/src/tutorials/npm-browser-packages/index.md @@ -1,6 +1,7 @@ -# Tutorial +# npm Browser Package Tutorial -The goal of this tutorial is to introduce you to the `wasm-pack` workflow. +The goal of this tutorial is to introduce you to the `wasm-pack` workflow by building a small npm +package designed to be used in a browser application. This tutorial is aimed at folks who are both beginners to WebAssembly and Rust- you don't need much Rust knowledge to complete this tutorial. diff --git a/docs/src/tutorial/packaging-and-publishing.md b/docs/src/tutorials/npm-browser-packages/packaging-and-publishing.md similarity index 100% rename from docs/src/tutorial/packaging-and-publishing.md rename to docs/src/tutorials/npm-browser-packages/packaging-and-publishing.md diff --git a/docs/src/tutorials/npm-browser-packages/project-setup/index.md b/docs/src/tutorials/npm-browser-packages/project-setup/index.md new file mode 100644 index 00000000..62236250 --- /dev/null +++ b/docs/src/tutorials/npm-browser-packages/project-setup/index.md @@ -0,0 +1 @@ +# Project setup diff --git a/docs/src/tutorials/npm-browser-packages/project-setup/manual-setup.md b/docs/src/tutorials/npm-browser-packages/project-setup/manual-setup.md new file mode 100644 index 00000000..88d32c17 --- /dev/null +++ b/docs/src/tutorials/npm-browser-packages/project-setup/manual-setup.md @@ -0,0 +1 @@ +# Manual Setup diff --git a/docs/src/project-setup/index.md b/docs/src/tutorials/npm-browser-packages/project-setup/project-setup/index.md similarity index 100% rename from docs/src/project-setup/index.md rename to docs/src/tutorials/npm-browser-packages/project-setup/project-setup/index.md diff --git a/docs/src/project-setup/manual-setup.md b/docs/src/tutorials/npm-browser-packages/project-setup/project-setup/manual-setup.md similarity index 100% rename from docs/src/project-setup/manual-setup.md rename to docs/src/tutorials/npm-browser-packages/project-setup/project-setup/manual-setup.md diff --git a/docs/src/project-setup/using-a-template.md b/docs/src/tutorials/npm-browser-packages/project-setup/project-setup/using-a-template.md similarity index 100% rename from docs/src/project-setup/using-a-template.md rename to docs/src/tutorials/npm-browser-packages/project-setup/project-setup/using-a-template.md diff --git a/docs/src/tutorials/npm-browser-packages/project-setup/using-a-template.md b/docs/src/tutorials/npm-browser-packages/project-setup/using-a-template.md new file mode 100644 index 00000000..7a91e262 --- /dev/null +++ b/docs/src/tutorials/npm-browser-packages/project-setup/using-a-template.md @@ -0,0 +1 @@ +# Using a Template diff --git a/docs/src/tutorial/template-deep-dive.md b/docs/src/tutorials/npm-browser-packages/template-deep-dive.md similarity index 100% rename from docs/src/tutorial/template-deep-dive.md rename to docs/src/tutorials/npm-browser-packages/template-deep-dive.md diff --git a/docs/src/tutorials/npm-browser-packages/template-deep-dive/building-your-project.md b/docs/src/tutorials/npm-browser-packages/template-deep-dive/building-your-project.md new file mode 100644 index 00000000..08caa870 --- /dev/null +++ b/docs/src/tutorials/npm-browser-packages/template-deep-dive/building-your-project.md @@ -0,0 +1 @@ +# Building your project diff --git a/docs/src/tutorial/template-deep-dive/cargo-toml.md b/docs/src/tutorials/npm-browser-packages/template-deep-dive/cargo-toml.md similarity index 100% rename from docs/src/tutorial/template-deep-dive/cargo-toml.md rename to docs/src/tutorials/npm-browser-packages/template-deep-dive/cargo-toml.md diff --git a/docs/src/tutorial/template-deep-dive/index.md b/docs/src/tutorials/npm-browser-packages/template-deep-dive/index.md similarity index 100% rename from docs/src/tutorial/template-deep-dive/index.md rename to docs/src/tutorials/npm-browser-packages/template-deep-dive/index.md diff --git a/docs/src/tutorial/template-deep-dive/src-lib-rs.md b/docs/src/tutorials/npm-browser-packages/template-deep-dive/src-lib-rs.md similarity index 100% rename from docs/src/tutorial/template-deep-dive/src-lib-rs.md rename to docs/src/tutorials/npm-browser-packages/template-deep-dive/src-lib-rs.md diff --git a/docs/src/tutorial/template-deep-dive/src-utils-rs.md b/docs/src/tutorials/npm-browser-packages/template-deep-dive/src-utils-rs.md similarity index 100% rename from docs/src/tutorial/template-deep-dive/src-utils-rs.md rename to docs/src/tutorials/npm-browser-packages/template-deep-dive/src-utils-rs.md diff --git a/docs/src/tutorial/using-your-library.md b/docs/src/tutorials/npm-browser-packages/using-your-library.md similarity index 100% rename from docs/src/tutorial/using-your-library.md rename to docs/src/tutorials/npm-browser-packages/using-your-library.md diff --git a/docs/src/tutorials/standalone-wasm-binaries/index.md b/docs/src/tutorials/standalone-wasm-binaries/index.md new file mode 100644 index 00000000..519604f6 --- /dev/null +++ b/docs/src/tutorials/standalone-wasm-binaries/index.md @@ -0,0 +1 @@ +# Standalone WASM Binaries