DEV Community

Cover image for Writing components in TypeScript with jco - WebAssembly Component Model
Tophe
Tophe

Posted on

Writing components in TypeScript with jco - WebAssembly Component Model

This part isn’t required to use the project — but if you want to experiment with writing plugins in TypeScript, here’s how it works.

The downsides of writing plugins in TypeScript is mostly that your .wasm file will be much larger than the one compiled from rust or C:

  • ~100KB of wasm for the rust plugin
  • ~12MB of wasm for the TypeScript plugin

The reason is that a JavaScript runtime needs to be embedded in the .wasm file, which is not the case for the rust plugin.

More about the SpiderMonkey runtime embedding.

It is setup in the project, however, I don't rely on plugins written in TypeScript for the moment as would be too much of a performance hit (mostly for the web host).

import type { plugin as pluginApi } from "./types/plugin-api";

export const plugin: typeof pluginApi = {
  name: () => "echo",
  man: () => "...",
  run: (payload: string) => {
    return {
      status: "success",
      stdout: payload,
      stderr: undefined,
    };
  },
};

Enter fullscreen mode Exit fullscreen mode

The jco toolchain helps compile JS/TS code into WebAssembly components.

Build Steps

  1. Generate TypeScript types:
cd packages/plugin-name
jco types --world-name plugin-api --out-dir ./src/types ../../crates/pluginlab/wit
Enter fullscreen mode Exit fullscreen mode
  1. Bundle your TS code into a single file (using rolldown or another bundler).
rolldown ./src/component.ts --file ./dist/component.js
Enter fullscreen mode Exit fullscreen mode
  1. Componentize it:
jco componentize ./dist/component.js \
  --wit ../../crates/pluginlab/wit \
  --world-name plugin-api \
  --out ./dist/component.wasm \
  --disable http --disable random
Enter fullscreen mode Exit fullscreen mode
  1. (Optional) Optimize the resulting .wasm file:
jco opt ./dist/component.wasm -o ./dist/component-opt.wasm
Enter fullscreen mode Exit fullscreen mode

Example: package.json Scripts

{
  "wit-types": "jco types ...",
  "bundle": "rolldown ...",
  "componentize": "jco componentize ...",
  "build": "npm run wit-types && npm run bundle && npm run componentize",
  "optimize": "jco opt ...",
  "typecheck": "tsc --noEmit"
}
Enter fullscreen mode Exit fullscreen mode

📎 Here are links to the implementation of the plugin-echo plugin in TypeScript in the project.

Top comments (0)