Rust WebAssembly guide
By following this guide, you will learn how to build a Worker entirely in the Rust programming language. You will accomplish this using the workers-rs
crate, which makes Runtime APIs and bindings to developer platform products, such as Workers KV, R2, and Queues, available directly from your Rust code.
Prerequisites
Before starting this guide, make sure you have:
$ rustup target add wasm32-unknown-unknown
1. Create a new project with Wrangler
Use wrangler generate
to create a new project from Cloudflare’s workers-rs
template.
$ npx wrangler generate hello-world-rust https://github.com/cloudflare/workers-sdk/templates/experimental/worker-rust
Your project will be created in a new directory (hello-world-rust
). To view the new directory’s files:
$ cd hello-world-rust
You will find the following files and folders in the hello-world-rust
directory:
Cargo.toml
- The standard project configuration file for Rust’sCargo
package manager. The template pre-populates some best-practice settings for building for Wasm on Workers.README.md
- Boilerplate readme for working with the template project.package.json
- NPM configuration for the template project which specifies useful commands (dev
anddeploy
), and Wrangler as a dev-dependency.wrangler.toml
- Wrangler configuration, pre-populated with a custom build command to invokeworker-build
(Refer to Wrangler Bundling).src
- Rust source directory, pre-populated with simple Hello World Worker.
2. Develop locally
After you have created your first Worker, run the wrangler dev
command to start a local server for developing your Worker. This will allow you to test your Worker in development.
$ npx wrangler dev
If you have not used Wrangler before, it will try to open your web browser to login with your Cloudflare account.
Go to http://localhost:8787 to review your Worker running. Any changes you make to your code will trigger a rebuild, and reloading the page will show you the up-to-date output of your Worker.
3. Write your Worker code
With your new project generated, write your Worker code. Find the entrypoint to your Worker in src/lib.rs
:
use worker::*;
#[event(fetch)]
async fn main(req: Request, env: Env, ctx: Context) -> Result<Response> { Response::ok("Hello, World!")
}
Related runtime APIs
workers-rs
provides a runtime API which closely matches Worker’s JavaScript API, and enables integration with Worker’s platform features. For detailed documentation of the API, refer to docs.rs/worker
.
event
macro
This macro allows you to easily define entrypoints to your Worker. The event
macro supports the following events:
fetch
- Invoked by an incoming HTTP request.scheduled
- Invoked byCron Triggers
.queue
- Invoked by incoming message batches from Queues (Requiresqueue
feature inCargo.toml
, refer to theworkers-rs
GitHub repository andqueues
feature flag).start
- Invoked when the Worker is first launched (such as, to install panic hooks).
fetch
parameters
The fetch
handler provides three arguments which match the JavaScript API:
An object representing the incoming request. This includes methods for accessing headers, method, path, Cloudflare properties, and body (with support for asynchronous streaming and JSON deserialization with Serde).
Provides access to Worker bindings.
Secret
- Secret value configured in Cloudflare dashboard or usingwrangler secret put
.Var
- Environment variable defined inwrangler.toml
.KvStore
- Workers KV namespace binding.ObjectNamespace
- Durable Object namespace binding.Fetcher
- Service binding to another Worker.Bucket
- R2 Bucket binding.
Provides access to waitUntil
(deferred asynchronous tasks) and passThroughOnException
(fail open) functionality.
Response
The fetch
handler expects a Response
return type, which includes support for streaming responses to the client asynchronously. This is also the return type of any subrequests made from your Worker. There are methods for accessing status code and headers, as well as streaming the body asynchronously or deserializing from JSON using Serde.
Router
Implements convenient routing API to serve multiple paths from one Worker. Refer to the Router
example in the worker-rs
GitHub repository.
4. Publish your Worker project
With your project configured, you can now deploy your Worker, to a *.workers.dev subdomain, or a custom domain, if you have one configured. If you have not configured any subdomain or domain, Wrangler will prompt you during the publish process to set one up.
$ npx wrangler publish
Preview your Worker at <YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev
.
After completing these steps, you will have a basic Rust-based Worker deployed. From here, you can add crate dependencies and write code in Rust to implement your Worker application. If you would like to know more about the inner workings of how Rust compiled to Wasm is supported by Workers, the next section outlines the libraries and tools involved.
How this deployment works
Wasm Workers are invoked from a JavaScript entrypoint script which is created automatically for you when using workers-rs
.
JavaScript Plumbing (wasm-bindgen
)
To access platform features such as bindings, Wasm Workers must be able to access methods from the JavaScript runtime API.
This interoperability is achieved using wasm-bindgen
, which provides the glue code needed to import runtime APIs to, and export event handlers from, the Wasm module. wasm-bindgen
also provides js-sys
, which implements types for interacting with JavaScript objects. In practice, this is an implementation detail, as workers-rs
’s API handles conversion to and from JavaScript objects, and interaction with imported JavaScript runtime APIs for you.
Async (wasm-bindgen-futures
)
wasm-bindgen-futures
(part of the wasm-bindgen
project) provides interoperability between Rust
Futures and JavaScript Promises. workers-rs
invokes the entire event handler function using spawn_local
, meaning that you can program using async Rust, which is turned
into a single JavaScript Promise and run on the JavaScript event loop. Calls to imported JavaScript runtime APIs are automatically converted to Rust Futures that can be easily invoked from async Rust functions.
Bundling (worker-build
)
To run the resulting Wasm binary on Workers, workers-rs
includes a build tool called worker-build
which:
- Creates a JavaScript entrypoint script that properly invokes the module using
wasm-bindgen
’s JavaScript API. - Invokes
web-pack
to minify and bundle the JavaScript code. - Outputs a directory structure that Wrangler can use to bundle and publish the final Worker.
worker-build
is invoked by default in the template project using a custom build command specified in wrangler.toml
.
Binary Size (wasm-opt
)
Unoptimized Rust Wasm binaries can be large and may exceed Worker bundle size limits or experience long startup times. The template project pre-configures several useful size optimizations in your Cargo.toml
file:
[profile.release]
lto = true
strip = true
codegen-units = 1
Finally, worker-bundle
automatically invokes wasm-opt
to further optimize binary size before upload.