Skip to main content

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

  1. Download wws:

    curl -fsSL https://workers.wasmlabs.dev/install | bash
  2. 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"
  3. 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.

  1. 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.js
    const reply = (request) => {
    return new Response("Hello Wasm!");
    }

    // Subscribe to the Fetch event
    addEventListener("fetch", event => {
    return event.respondWith(reply(event.request));
    });
  2. 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.js
    const 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));
    });
  3. Save the file and run your worker with wws. If you didn't download the wws 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:8080
  4. Finally, 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:

  1. First, create a counter.js file. It will access the KV store through the Cache object:

    ./counter.js
    const 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));
    });
  2. 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 have counter.js and counter.toml in the same folder:

    ./counter.toml
    name = "counter"
    version = "1"

    [data]
    [data.kv]
    namespace = "counter"
  3. Save the file and run your worker with wws. If you didn't download the wws 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:8080
  4. Finally, 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:

  1. First, create an index.js file. It will call the {JSON} Placeholder API using the fetch method:

    ./index.js
    const 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));
    });
  2. 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 and index.toml in the same folder:

    ./index.toml
    name = "fetch"
    version = "1"

    [features]
    [features.http_requests]
    allowed_methods = ["GET"]
    allowed_hosts = ["jsonplaceholder.typicode.com"]
  3. Save the file and run your worker with wws. If you didn't download the wws 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:8080
  4. Finally, 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:

./envs.toml
name = "envs"
version = "1"

[vars]
MESSAGE = "Hello 👋! This message comes from an environment variable"

Now, you can use the MESSAGE constant directly:

./envs.js
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 StoreEnvironment VariablesDynamic RoutesFoldersHTTP Requests