JavaScript
Workers based on JavaScript work out of the box with Wasm Workers Server. The server integrates a JavaScript interpreter compiled into a WebAssembly module. Currently, the interpreter we support is quickjs and we are working on adding new ones.
Run a JavaScript example
Download
wws
:curl -fsSL https://workers.wasmlabs.dev/install | bash
Run the js-basic example from the Wasm Workers Server's repository:
wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-basic"
Access to http://localhost:8080.
Your first JavaScript worker
JavaScript workers are based on the Request / Response objects from the Web Fetch API. Your worker needs to listen to the fetch
event, which will include an associated Request
object. The worker function will receive the request and generate a Response
object to reply to the request.
In this example, the worker will get a request and print all the related information.
First, create a new
index.js
file with the following content. It is the minimum code you need to subscribe to the fetch event and return a valid response../index.jsconst reply = (request) => {
return new Response("Hello Wasm!");
}
// Subscribe to the Fetch event
addEventListener("fetch", event => {
return event.respondWith(reply(event.request));
});Now, you can add more content to the
reply
function to show the request information. In addition to that, let's add a response header../index.jsconst reply = (request) => {
// Body response
const body = `<!DOCTYPE html>
<body>
<h1>Hello from Wasm Workers Server</h1>
<p>Replying to ${request.url}</p>
<p>Method: ${request.method}</p>
<p>User Agent: ${request.headers.get("userAgent")}</p>
<p>Payload: ${request.body || "-"}</p>
<p>
This page was generated by a JavaScript file inside WebAssembly
</p>
</body>`;
// Build a new response
let response = new Response(body);
// Add a new header
response.headers.set("x-generated-by", "wasm-workers-server");
return response;
}
// Subscribe to the Fetch event
addEventListener("fetch", event => {
return event.respondWith(reply(event.request));
});Save the file and run your worker with
wws
. If you didn't download thewws
server yet, check our Getting Started guide.wws
⚙️ Loading routes from: .
🗺 Detected routes:
- http://127.0.0.1:8080/
=> index.js (name: default)
🚀 Start serving requests at http://127.0.0.1:8080Finally, open http://127.0.0.1:8080 in your browser.
Add a Key / Value store
Wasm Workers allows you to add a Key / Value store to your workers. Read more information about this feature in the Key / Value store section.
To add a KV store to your worker, follow these steps:
First, create a
counter.js
file. It will access the KV store through theCache
object:./counter.jsconst CACHE_KEY = "counter";
const reply = (request) => {
let counter = Cache.get(CACHE_KEY) || 0;
counter += 1;
Cache.set(CACHE_KEY, counter);
return new Response(`Counter: ${counter}`);
}
addEventListener("fetch", event => {
event.respondWith(reply(event.request));
});Create a
counter.toml
file with the following content. Note the name of the TOML file must match the name of the worker. In this case we havecounter.js
andcounter.toml
in the same folder:./counter.tomlname = "counter"
version = "1"
[data]
[data.kv]
namespace = "counter"Save the file and run your worker with
wws
. If you didn't download thewws
server yet, check our Getting Started guide.wws
⚙️ Loading routes from: .
🗺 Detected routes:
- http://127.0.0.1:8080/counter
=> counter.js (name: default)
🚀 Start serving requests at http://127.0.0.1:8080Finally, open http://127.0.0.1:8080/counter in your browser.
Send an HTTP request (fetch)
Wasm Workers allows you to send HTTP requests from your workers. Read more information about this feature in the HTTP Requests section.
To perform HTTP requests from your worker, follow these steps:
First, create an
index.js
file. It will call the {JSON} Placeholder API using the fetch method:./index.jsconst reply = async (_req) => {
// Body response
let body;
try {
let res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
let json = await res.json();
// Build a new response.
// Add some basic sanitization
body = `<!DOCTYPE html>
<head>
<title>JSON Placeholder request</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta charset="UTF-8">
</head>
<body>
<main>
<h1>Hello from Wasm Workers Server 👋</h1>
<p>The post title is: ${json.title}</p>
</main>
</body>`;
} catch (e) {
body = `There was an error with the request: ${e}`;
}
return new Response(body);
}
addEventListener("fetch", event => {
event.respondWith(reply(event.request));
});Create an
index.toml
file with the following content. It enables the worker to perform HTTP requests to that host given that, by default, HTTP requests are forbidden.Note the name of the TOML file must match the name of the worker. In this case we have
index.js
andindex.toml
in the same folder:./index.tomlname = "fetch"
version = "1"
[features]
[features.http_requests]
allowed_methods = ["GET"]
allowed_hosts = ["jsonplaceholder.typicode.com"]Save the file and run your worker with
wws
. If you didn't download thewws
server yet, check our Getting Started guide.wws
⚙️ Preparing the project from: .
⚙️ Loading routes from: .
⏳ Loading workers from 1 routes...
✅ Workers loaded in 135.717667ms.
- http://127.0.0.1:8080/
=> ./index.js
🚀 Start serving requests at http://127.0.0.1:8080Finally, open http://127.0.0.1:8080 in your browser.
Dynamic routes
You can define dynamic routes by adding route parameters to your worker files (like [id].js
). To read them in JavaScript, access to the req.params
object:
/**
* Builds a reply to the given request
*/
const reply = (req) => {
// Build a new response
return new Response(`Hey! I got this parameter: ${req.params.id}`);
}
// Subscribe to the Fetch event
addEventListener("fetch", event => {
return event.respondWith(reply(event.request));
});
Read environment variables
Environment variables are configured via the related TOML configuration file. These variables are directly injected as global constants in your worker. To read them, just use the same name you configured in your TOML file:
name = "envs"
version = "1"
[vars]
MESSAGE = "Hello 👋! This message comes from an environment variable"
Now, you can use the MESSAGE
constant directly:
const reply = (request) => {
// Body response
const body = JSON.stringify({
success: true,
// Here you can read the constant directly
message: MESSAGE
}, null, 2);
// Build a new response
let response = new Response(body, {
headers: {
"content-type": "application/json;charset=UTF-8"
}
});
return response;
}
// Subscribe to the Fetch event
addEventListener("fetch", event => {
return event.respondWith(reply(event.request));
});
If you prefer, you can configure the environment variable value dynamically by following these instructions.
Other examples
Feature compatibility
Workers' features that are available in JavaScript:
K/V Store | Environment Variables | Dynamic Routes | Folders | HTTP Requests |
---|---|---|---|---|
✅ | ✅ | ✅ | ❌ | ✅ |