Skip to content
This repository has been archived by the owner on Nov 8, 2021. It is now read-only.

Commit

Permalink
Merge pull request rustwasm#576 from rustwasm/j-tut
Browse files Browse the repository at this point in the history
webpack tutorial and some docs nits
  • Loading branch information
ashleygwilliams authored Mar 15, 2019
2 parents 912b9b1 + 54e974e commit a1b0fd2
Show file tree
Hide file tree
Showing 23 changed files with 203 additions and 34 deletions.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down
1 change: 1 addition & 0 deletions docs/public/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
position: relative;
float: left;
margin-bottom: 0;
bottom: -5px;
}

.navbar-logo a img {
Expand Down
29 changes: 17 additions & 12 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,27 @@

- [Prerequisites](./prerequisites/index.md)
- [npm (optional)](./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)
- [`test`](./commands/test.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)
- [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`](./tutorials/npm-browser-packages/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)
- [`Cargo.toml` Configuration](./cargo-toml-configuration.md)
- [Contributing](./contributing.md)
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions docs/src/tutorials/hybrid-applications-with-webpack/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 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 read and followed the [Prerequisites](../prerequisites/index.html).

[Rust]: https://www.rust-lang.org
[Node.js]: https://nodejs.org
[npm]: https://npmjs.com
[`rust-webpack-template`]: https://github.com/rustwasm/rust-webpack-template
Original file line number Diff line number Diff line change
@@ -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!
9 changes: 9 additions & 0 deletions docs/src/tutorials/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Tutorials

We have two tutorials that help you get started with `wasm-pack`:

- If you want to create and publish a package: [npm browser packages]
- If you'd like to develop a Wasm library alongside a JavaScript application using Webpack: [Hybrid applications with Webpack]

[npm browser packages]: npm-browser-packages/index.html
[Hybrid applications with Webpack]: hybrid-applications-with-webpack/index.html
24 changes: 24 additions & 0 deletions docs/src/tutorials/npm-browser-packages/building-your-package.md
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Building your project
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Cargo.toml

`Cargo.toml` is the manifest file for Rust's package manager, `cargo`. This file contains
`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.

[`cargo`]: https://doc.rust-lang.org/cargo/

There's a bunch of metadata that the template gives us, but there are three key parts to discuss:

1. [`crate-type`](#a1-crate-type)
Expand Down Expand Up @@ -40,11 +42,13 @@ You can read more about linking and crate types, [here](https://doc.rust-lang.or

## 2. `wasm-bindgen` dependency

`wasm-bindgen` is our most important dependency. This package allows us to use the
[`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.

[`wasm-bindgen`]: https://rustwasm.github.io/docs/wasm-bindgen/

```toml
wasm-bindgen = "0.2"
```
Expand All @@ -53,9 +57,15 @@ We'll see more about how to use this library when we discuss what has been gener

⚠️ 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.
However, that's not the case! In Rust, the `^` is implied. You can read more about this in the
[cargo documentation on specifying dependencies].

[cargo documentation on specifying dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html

## 3. `[features]` and `wee_alloc`, `console_error_panic_hook` dependencies
## 3. `[features]` and [`wee_alloc`], [`console_error_panic_hook`] dependencies

[`wee_alloc`]: https://github.com/rustwasm/wee_alloc
[`console_error_panic_hook`]: https://github.com/rustwasm/console_error_panic_hook

As part of our effort to design a template that helps people discover useful crates
for their particular use case, this template includes two dependencies that can be
Expand Down Expand Up @@ -95,8 +105,11 @@ use this crate later to optionally enable `console_error_panic_hook` or
By default, only `console_error_panic_hook` is enabled. To disable either
feature, we can remove its name from the `default` vector.

To learn more about these features, we discuss them in-depth in the `src/lib.rs` and
`src/utils.rs` sections.
To learn more about these features, we discuss them in-depth in the [`src/lib.rs`] and
[`src/utils.rs`] sections.

[`src/lib.rs`]: src-lib-rs.html
[`src/utils.rs`]: src-utils-rs.html

Briefly, they include:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ It contains three key parts:

---

We'll start with the most important part of `lib.rs` -- the two `#[wasm_bindgen]` functions. In many cases, this is the only part of `lib.rs` you will need to modify.
We'll start with the most important part of `lib.rs` -- the two `#[wasm_bindgen]` functions (which you can find at the bottom of the file). In many cases, this is the only part of `lib.rs` you will need to modify.

## 1. `#[wasm_bindgen]` functions

Expand Down Expand Up @@ -39,18 +39,14 @@ pub fn greet() {

If we were to write the `greet` function without the `#[wasm_bindgen]` attribute, then `greet` would not be easily accessible within JavaScript. Furthermore, we wouldn't be able to natively convert certain types such as `&str` between JavaScript and Rust. So, both the `#[wasm_bindgen]` attribute and the prior import of `alert` allow `greet` 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.
This is all you need to know to interface with JavaScript, at least to start! You can learn a bunch more by reading the
[`wasm-bindgen` documentation]!

## 2. Crate imports
[`wasm-bindgen` documentation]: https://rustwasm.github.io/docs/wasm-bindgen/

```rust
extern crate cfg_if;
extern crate wasm_bindgen;
```
If you are curious about the rest, read on.

In `Cargo.toml`, we included the crates `cfg_if` and `wasm_bindgen` as project dependencies.

Here, we explicitly declare that these crates will be used in `lib.rs`.
## 2. Crate imports

```rust
mod utils;
Expand All @@ -70,7 +66,8 @@ Either way, the contents of `utils.rs` define a single public function `set_pani
use cfg_if::cfg_if;
```

`use` allows us to conveniently refer to parts of a crate or module. For example, suppose the crate `cfg_if` contains a function `func`. It is always possible to call this function directly by writing `cfg_if::func()`. However, this is often tedious to write. If we first specify `use cfg_if::func;`, then `func` can be called by just writing `func()` instead.
`use` allows us to conveniently refer to parts of a crate or module. For example, suppose the crate `cfg_if` contains a function `func`. It is always possible to call this function directly by writing `cfg_if::func()`. However, this is often tedious to write. If we first specify `use cfg_if::func;`, then `func` can be called by just writing `func()` instead. You can learn more about how Rust let's you
write modular code in [this chapter of the book](https://doc.rust-lang.org/book/ch07-02-modules-and-use-to-control-scope-and-privacy.html).

With this in mind, this `use` allows us to call the macro `cfg_if!` inside the crate `cfg_if` without writing `cfg_if::cfg_if!`. We use `cfg_if!` to configure `wee_alloc`, which we will talk more about in a [separate section](./wee_alloc.md):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

Reducing the size of compiled WebAssembly code is important, since it is often transmitted over the Internet or placed on embedded devices.

*Want to learn more about code sizein the rustwasm toolchain? Check out this [documentation](https://rustwasm.github.io/docs/book/reference/code-size.html).

> `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.
Expand Down
1 change: 1 addition & 0 deletions docs/src/tutorials/standalone-wasm-binaries/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Standalone WASM Binaries

0 comments on commit a1b0fd2

Please sign in to comment.