$ npm install --save offroad
Add some "paths" entries to your tsconfig.json file:
// tsconfig.json
{
"compilerOptions": {
// ...
"paths": {
"worker:*.ts": ["./src/*.d.ts"],
"worker:*": ["./src/*.d", "./src/*.d.ts"]
}
}
}
Attach the Vite plugin:
// vite.config.ts
import { defineConfig } from "vite";
import { offroad } from "offroad/vite";
export default defineConfig({
plugins: [
offroad(),
],
});
Use define to define a potential bridge:
// example.ts
import { define } from "offroad";
// IMPORTANT: Must be `default` export!
export default define({
add(a: number, b: number): number {
return a + b;
},
});
Now, anywhere in your Vite application, you may use the example.ts file as per normal:
import example from "./example.ts";
let value = example.add(1, 2); //-> 3
However, you may also import the example.ts as a bridge to a Worker. This is done by adding the worker: prefix to your import statement.
Doing so allows you to interface with the file exactly the same, except now all methods are Promises!
import example from "worker:./example.ts";
let value = await example.add(1, 2); //-> 3
If are unsure if you want a Worker or not, or if you have dynamic/runtime conditions that determine your ability to use a Worker, you may use the offroad helper to conditionally load a module as a Bridge to a Worker or load the module directly:
import { offroad } from "offroad";
// Your custom logic
declare const useWorker: () => boolean;
const example = await offroad(useWorker, {
worker: () => import("worker:./example"),
fallback: () => import("./example"),
});
// Option 1:
// Always `await`
let foo = await example.add(2, 3); //-> 5
// Option 2:
// Use `isBridge` to determine if is Bridge (async) or not
import { isBridge } from "offroad";
if (isBridge(example)) {
// Bridge <-> Worker
await example.add(2, 3); //-> 5
} else {
// Direct / Main thread
example.add(2, 3); //-> 5
}
MIT © Luke Edwards