Skip to content

Commit 648d31c

Browse files
Merge pull request rustwasm#86 from mgattozzi/wasm-pack
Add the wasm-pack tutorial
2 parents dfc9dba + cf39661 commit 648d31c

11 files changed

+425
-0
lines changed

src/SUMMARY.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,11 @@
77
- [Tools](./tools.md)
88
- [Workflows](./workflows.md)
99
- [JavaScript Interoperation](./js-ffi.md)
10+
- [Tutorials](./tutorials.md)
11+
- [wasm-pack](./wasm-pack/introduction.md)
12+
- [Setup](./wasm-pack/setup.md)
13+
- [Project Initialization](./wasm-pack/initialize.md)
14+
- [Rust Code](./wasm-pack/rust-code.md)
15+
- [Package Code For npm](./wasm-pack/package-code.md)
16+
- [Run The Code From npm](./wasm-pack/run-the-code.md)
17+
- [Next Steps](./wasm-pack/next-steps.md)

src/tools.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ However, since Rust has the potential to be used for both development and toolin
1515
- [wasmparser] - A wasm binary decoder with optional validation, in Rust
1616
- [wasmtext] - prints wasm modules in text format, in Rust
1717
- [wasmstandalone] - standalone JIT-based wasm runner, in Rust, using Cretonne, in early development
18+
- [wasm-pack] - Package up your wasm for distribution on npm
1819

1920
There's also plenty of _space for tooling to be be built or rewritten in Rust_ for better synergy with the ecosystem. Some of them include:
2021
- [A wasm size profiler][wasmsizeprofiler]
@@ -36,3 +37,4 @@ This page is meant to be a living document, so feel free to send us a pull reque
3637
[wasmstandalone]: https://github.com/sunfishcode/wasmstandalone
3738
[wasmsizeprofiler]: https://github.com/rust-lang-nursery/rust-wasm/issues/20
3839
[ewasm]: https://github.com/ewasm
40+
[wasm-pack]: https://github.com/ashleygwilliams/wasm-pack

src/tutorials.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Tutorials
2+
3+
There are a wide variety of tools available in the ecosystem and we want to provide a centralized
4+
way to show you how to get using them more in depth than a basic readme.

src/wasm-pack/initialize.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Project Initialization
2+
3+
Now that we've installed all of our tools and setup our npm account we can actually start coding!
4+
We'll be writing up a small crate that adds two numbers and outputs the numbers. While this will
5+
be a simple example, we're really trying to focus on how to use wasm-pack. You'll be provided links
6+
to other resources so you can make more complicated code to package and ship them to npm!
7+
8+
Let's get started then! First off run this command to create our project:
9+
10+
```bash
11+
$ cargo new --lib wasm-add
12+
```
13+
14+
This will create a new Rust project in a directory called `wasm-add`. We've also specified that
15+
we're building a library, since we'll be calling this code from JS.
16+
17+
Now just:
18+
19+
```bash
20+
$ cd wasm-add
21+
```
22+
23+
You'll find everything in here ready to get started. First though we'll need to add a dependency to
24+
our code and make a few small changes. Open up your `Cargo.toml` file. You should see something like
25+
this inside:
26+
27+
```toml
28+
[package]
29+
name = "wasm-add"
30+
version = "0.1.0"
31+
authors = ["Michael Gattozzi <[email protected]>"]
32+
33+
[dependencies]
34+
```
35+
36+
This configuration file sets up everything we need to get started but we'll need a few extra fields
37+
and settings to get this to work for wasm and be ready for npm
38+
39+
```toml
40+
[package]
41+
name = "wasm-add"
42+
version = "0.1.0"
43+
authors = ["Michael Gattozzi <[email protected]>"]
44+
description = "Code used to demonstrate how to use wasm-pack"
45+
license = "MIT/Apache-2.0"
46+
repository = "https://github.com/mgattozzi/wasm-add"
47+
48+
[lib]
49+
crate-type = ["cdylib"]
50+
51+
[dependencies]
52+
wasm-bindgen="0.1"
53+
```
54+
55+
First off lets look at the last three fields added to the package section `description`, `license`,
56+
and `repository` npm requires this metadata and so `wasm-pack` won't package your code up until you
57+
have them set. There are more fields that you can add that are more specific to `crates.io` that you
58+
can find [here](https://doc.rust-lang.org/cargo/reference/manifest.html) but for the sake of this
59+
tutorial that's all you need for that section.
60+
61+
You'll also notice we add a new section titled `[lib]`. In here we added this line:
62+
63+
```toml
64+
crate-type = ["cdylib"]
65+
```
66+
67+
Normally rust compiles the code for the library in a format meant for other Rust packages. We want
68+
our code to work with wasm though! We specify that it's a dynamic library that's C compatible. This
69+
sounds a bit weird but the `wasm32` target will know to interpret this option and instead produce
70+
a wasm binary properly. This is meant to get `cargo` to pass the right parameters to the compiler!
71+
72+
Alright the last thing we added was this to the `[dependencies]` section:
73+
74+
```toml
75+
wasm-bindgen="0.1"
76+
```
77+
78+
This is the `wasm-bindgen` crate. We'll be using it very shortly to make our functions work nicely
79+
with wasm and not have to worry about a lot of nitty gritty details.
80+
81+
We've got our package's metadata all setup so let's actually write some code!

src/wasm-pack/introduction.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Introduction
2+
3+
`wasm-pack` is a brand new tool designed to make packaging up binaries that include wasm (that may
4+
or may not have JS in them) and make publishing them on npm easy to do. We can't necessarily
5+
distribute Rust code to developers directly and expect them
6+
to build it from scratch. npm is used to install packages for frontend work but it doesn't know how
7+
to compile Rust! With wasm though it's not a problem. Once it's compiled it's all good to go.
8+
However, getting it ready to be distributed, packaging it up properly for npm, and then sending it
9+
to npm can be a bit of a hassle. `wasm-pack` is here to make that easier.
10+
11+
We'll step through creating a simple Rust library, using `wasm-pack` to get it ready for
12+
distribution, sending it to npm, then using it as a package from npm to verify it works!
13+
14+
As with all software in the early stages this is bleeding edge! Expect some nicks and bruises! If
15+
you run into issues or a bug please file an issue over at it's [repo].
16+
17+
[repo]: https://github.com/ashleygwilliams/wasm-pack/issues

src/wasm-pack/next-steps.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Next Steps
2+
3+
This was an introduction to wasm-pack but also using wasm code from npm. From here you could
4+
actually improve on the project setup, expand out what your wasm code can actually do, or expand out
5+
how you would use the package you've created. The whole wasm space is completely open so there's no
6+
limit to what you can and can't do really! Go out there and try some cool new things. Happy hacking!

src/wasm-pack/package-code.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Package Code for npm
2+
3+
We've made our code so now we need to package it all up. In your project directory run the following
4+
command:
5+
6+
```bash
7+
$ wasm-pack init --scope MYSCOPE
8+
```
9+
10+
where `MYSCOPE` is your name or something. Normally you could just type `wasm-pack init` but since
11+
other people are doing this tutorial as well we don't want conflicts with the `wasm-add` package
12+
name! This command when run does a few things:
13+
14+
1. It'll compile your code to wasm if you haven't already
15+
2. It'll generate a pkg folder with the wasm file, a JS wrapper file around the wasm, your README,
16+
and a `package.json` file.
17+
18+
This is everything you need to upload your code to npm! Let's do just that!
19+
20+
First off you'll need to login to npm with the account you made earlier if you didn't already have
21+
one:
22+
23+
```bash
24+
$ npm login
25+
```
26+
27+
Next you'll need to go into the `pkg` directory and actually upload the package:
28+
29+
```bash
30+
$ cd pkg
31+
$ npm publish --access=public
32+
```
33+
34+
Now normally if things are not scoped you can just do `npm publish` but if you give it a scope
35+
you'll need to tell npm that this is actually public so it can publish it. We need to do that here
36+
since we gave our packages a scope to avoid conflicting with each other! Next up is actually running
37+
the code and verifying we got it from npm and how we can use that code.

src/wasm-pack/run-the-code.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Run The Code From npm
2+
3+
Alright let's make a new small directory to test that we can now run this code and pull it from npm.
4+
5+
```bash
6+
$ mkdir test
7+
$ cd test
8+
```
9+
10+
Now we need to create a `package.json` file that looks like this:
11+
12+
```json
13+
{
14+
"scripts": {
15+
"serve": "webpack-dev-server"
16+
},
17+
"dependencies": {
18+
"@MYSCOPE/wasm-add": "^0.1.0"
19+
},
20+
"devDependencies": {
21+
"webpack": "^4.0.1",
22+
"webpack-cli": "^2.0.10",
23+
"webpack-dev-server": "^3.1.0"
24+
}
25+
}
26+
```
27+
28+
where `MYSCOPE` is whatever you used before. You can expand this to be a more complete file but
29+
we're really just trying to verify that this works!
30+
31+
Next up we'll need to create a small webpack configuration so that we can use the
32+
`webpack-dev-server` to serve the wasm file properly. It should be noted that webpack isn't
33+
a requirement. It's just what was chosen for this tutorial. You just need something to server the
34+
code! Here's what it should look like:
35+
36+
```javascript
37+
const path = require('path');
38+
module.exports = {
39+
entry: "./index.js",
40+
output: {
41+
path: path.resolve(__dirname, "dist"),
42+
filename: "index.js",
43+
},
44+
mode: "development"
45+
};
46+
```
47+
48+
This tells webpack that if it's going to start things up use `index.js`. Before we do that though
49+
we'll need to setup a small html file. Create a new file called `index.html` and put this inside it:
50+
51+
```html
52+
<html>
53+
<head>
54+
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
55+
</head>
56+
<body>
57+
<script src='./index.js'></script>
58+
</body>
59+
</html>
60+
```
61+
62+
We're almost set. Now we need to setup our JS file so that we can run some wasm code!
63+
Make a file called `index.js` and put this inside of it:
64+
65+
```javascript
66+
const js = import("./node_modules/@MYSCOPE/wasm-add/wasm_add.js");
67+
js.then(js => {
68+
js.alert_add(3,2);
69+
});
70+
```
71+
72+
Since web pack [can't load wasm synchronously yet](https://github.com/webpack/webpack/issues/6615)
73+
we are using the import statement above followed
74+
by the promise in order to load it properly. This is what lets us then call `alert_add`. We're
75+
importing from the `node_module` folder we haven't gotten yet so let's import all of our
76+
dependencies finally and run the example!
77+
78+
```bash
79+
$ npm install
80+
$ npm run serve
81+
```
82+
83+
Then in a web browser navigate to `http://localhost:8080` you should see something like this:
84+
85+
![An alert box saying "Hello from Rust! 3 + 2 = 5"](/wasm-pack/wasm-pack.png)
86+
87+
If you did congrats you've successfully uploaded your first bit of wasm code to npm and used it
88+
properly!

0 commit comments

Comments
 (0)