wasm-pack build
The wasm-pack build command creates the files necessary for JavaScript
interoperability and for publishing a package to npm. This involves compiling
your code to wasm and generating a pkg folder. This pkg folder will contain the
wasm binary, a JS wrapper file, your README, and a package.json file.
The pkg directory is automatically .gitignored by default, since it contains
build artifacts which are not intended to be checked into version
control.0 You can disable this with the
--no-gitignore flag.
Path
The wasm-pack build command can be given an optional path argument, e.g.:
wasm-pack build examples/js-hello-world
This path should point to a directory that contains a Cargo.toml file. If no
path is given, the build command will run in the current directory.
Output Directory
By default, wasm-pack will generate a directory for its build output called pkg.
If you’d like to customize this you can use the --out-dir flag.
wasm-pack build --out-dir out
The above command will put your build artifacts in a directory called out, instead
of the default pkg.
Generated file names
Flag --out-name sets the prefix for output file names. If not provided, package name is used instead.
Usage examples, assuming our crate is named dom:
wasm-pack build
# will produce files
# dom.d.ts dom.js dom_bg.d.ts dom_bg.wasm package.json README.md
wasm-pack build --out-name index
# will produce files
# index.d.ts index.js index_bg.d.ts index_bg.wasm package.json README.md
Profile
The build command accepts an optional profile argument: one of --dev,
--profiling, or --release. If none is supplied, then --release is used.
This controls whether debug assertions are enabled, debug info is generated, and which (if any) optimizations are enabled.
| Profile | Debug Assertions | Debug Info | Optimizations | Notes |
|---|---|---|---|---|
--dev | Yes | Yes | No | Useful for development and debugging. |
--profiling | No | Yes | Yes | Useful when profiling and investigating performance issues. |
--release | No | No | Yes | Useful for shipping to production. |
The --dev profile will build the output package using cargo’s default
non-release profile. Building this way is
faster but applies few optimizations to the output, and enables debug assertions
and other runtime correctness checks. The --profiling and --release profiles
use cargo’s release profile, but the former enables debug info as well, which
helps when investigating performance issues in a profiler.
The exact meaning of the profile flags may evolve as the platform matures.
Target
The build command accepts a --target argument. This will customize the JS
that is emitted and how the WebAssembly files are instantiated and loaded. For
more documentation on the various strategies here, see the documentation on
using the compiled output.
wasm-pack build --target nodejs
| Option | Usage | Description |
|---|---|---|
not specified or bundler | Bundler | Outputs JS that is suitable for interoperation with a Bundler like Webpack. You’ll import the JS and the module key is specified in package.json. sideEffects: false is by default. |
nodejs | Node.js | Outputs JS that uses CommonJS modules, for use with a require statement. main key in package.json. |
web | Native in browser | Outputs JS that can be natively imported as an ES module in a browser, but the WebAssembly must be manually instantiated and loaded. |
no-modules | Native in browser | Same as web, except the JS is included on a page and modifies global state, and doesn’t support as many wasm-bindgen features as web |
deno | Deno | Outputs JS that can be natively imported as an ES module in deno. |
Scope
The build command also accepts an optional --scope argument. This will scope
your package name, which is useful if your package name might conflict with
something in the public registry. For example:
wasm-pack build examples/js-hello-world --scope test
This command would create a package.json file for a package called
@test/js-hello-world. For more information about scoping, you can refer to
the npm documentation here.
Mode
The build command accepts an optional --mode argument.
wasm-pack build examples/js-hello-world --mode no-install
| Option | Description |
|---|---|
no-install | wasm-pack build implicitly and create wasm binding without installing wasm-bindgen. |
normal | do all the stuffs of no-install with installed wasm-bindgen. |
Extra options
The build command can pass extra options straight to cargo build even if
they are not supported in wasm-pack. To use them simply add the extra arguments
at the very end of your command, just as you would for cargo build. For
example, to build the previous example using cargo’s offline feature:
wasm-pack build examples/js-hello-world --mode no-install -- --offline
Skip .gitignore
By default, wasm-pack creates a .gitignore file in the output directory
containing *, which prevents the build artifacts from being checked into
version control. If you want to commit the pkg directory to your repository
(e.g. for GitHub Pages, Deno packages, or monorepo setups), you can use the
--no-gitignore flag to skip generating the .gitignore file:
wasm-pack build --no-gitignore
This is also available with --target web and other targets.
Panic strategy
By default, Rust panics in WebAssembly compile with panic=abort, which aborts
the WebAssembly instance on panic. The --panic-unwind flag changes this so
panics can be caught at FFI boundaries and converted to JavaScript exceptions
by tools like wasm-bindgen’s catch-unwind support.
wasm-pack build --panic-unwind
This flag:
- Invokes
cargowith the nightly toolchain (cargo +nightly build). - Adds
-Z build-std=std,panic_unwindto rebuildstdwith unwinding support. - Sets
RUSTFLAGS=-Cpanic=unwind(preserving any user-providedRUSTFLAGS).
The first time you use --panic-unwind, wasm-pack will install any missing
prerequisites via rustup:
- The nightly toolchain
- The
rust-srccomponent for nightly - The
wasm32-unknown-unknowntarget for nightly
If you are not using rustup you must install these prerequisites manually.
See Non-rustup setups.
Note:
wasm-packonly handles producing the.wasm. The actual “panic = recoverable JavaScript exception” behaviour requires runtime glue from your bindings layer (e.g.wasm-bindgen’s catch-unwind feature). With just--panic-unwindand no runtime glue, panics still terminate the instance — they are merely unwound rather than aborted.
--panic-unwind is also available for wasm-pack test.
64-bit WebAssembly (wasm64-unknown-unknown)
The cargo target triple is the source of truth for which WebAssembly ABI
wasm-pack builds. To produce a memory64 binary, declare the target the
cargo-native way — either in .cargo/config.toml:
# .cargo/config.toml
[build]
target = "wasm64-unknown-unknown"
or as an extra cargo argument:
wasm-pack build -- --target wasm64-unknown-unknown
or via CARGO_BUILD_TARGET=wasm64-unknown-unknown in the environment.
wasm64-unknown-unknown is a tier-3 Rust target, so rustup
has no prebuilt artifacts for it. You need to provide two pieces yourself
via cargo’s native config:
-
A nightly toolchain —
rust-toolchain.tomlis the cargo-native way to pin one to your project:# rust-toolchain.toml [toolchain] channel = "nightly" components = ["rust-src"]Or set
RUSTUP_TOOLCHAIN=nightlyfor one-off invocations. -
-Z build-stdto buildstdfrom source, since there is no prebuilt one. Add to your.cargo/config.toml:[unstable] build-std = ["std", "panic_abort"]Or pass
-Z build-std=std,panic_abortas an extra cargo argument.
wasm-pack itself stays out of the cargo invocation — it does not inject
+nightly or -Z build-std (those would override your toolchain pin or
surprise users who hadn’t intended a nightly build). What it does do when
it sees a wasm64-* triple:
- Verifies the active toolchain is nightly, with a helpful error pointing at the config above if it isn’t.
- Installs the
rust-srccomponent for the active toolchain viarustupif missing. - Does not attempt
rustup target add wasm64-*(which would always fail for a tier-3 target). - Passes
--enable-memory64towasm-optso the optimiser accepts 64-bit memories and tables.
0 If you need to include additional assets in the pkg
directory and your NPM package, we intend to have a solution for your use case
soon. You can use --no-gitignore to omit the .gitignore file in the
meantime. ↩