Skip to content

Commit

Permalink
Dynamically load the webworker blob (#83)
Browse files Browse the repository at this point in the history
* dynamically load the webworker blob

* dynamic loading of web worker

* switch to jsdelivr
  • Loading branch information
seveibar authored Jan 19, 2025
1 parent cfb30b1 commit a7a1680
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 15 deletions.
35 changes: 21 additions & 14 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,37 @@ export const createCircuitWebWorker = async (
)
}

const rawWorker = new Worker(
configuration.webWorkerUrl ??
"https://unpkg.com/@tscircuit/eval-webworker/dist/webworker/index.js",
{ type: "module" },
)
const webWorker = Comlink.wrap<InternalWebWorkerApi>(rawWorker)
let workerBlobUrl =
configuration.webWorkerBlobUrl ?? configuration.webWorkerUrl

if (!workerBlobUrl) {
const cdnUrl =
"https://cdn.jsdelivr.net/npm/@tscircuit/eval-webworker/dist/webworker/index.js"

const workerBlob = await fetch(cdnUrl).then((res) => res.blob())
workerBlobUrl = URL.createObjectURL(workerBlob)
}

const rawWorker = new Worker(workerBlobUrl, { type: "module" })
const comlinkWorker = Comlink.wrap<InternalWebWorkerApi>(rawWorker)

if (configuration.snippetsApiBaseUrl) {
await webWorker.setSnippetsApiBaseUrl(configuration.snippetsApiBaseUrl)
await comlinkWorker.setSnippetsApiBaseUrl(configuration.snippetsApiBaseUrl)
}

// Create a wrapper that handles events directly through circuit instance
const wrapper: CircuitWebWorker = {
clearEventListeners: webWorker.clearEventListeners.bind(webWorker),
execute: webWorker.execute.bind(webWorker),
executeWithFsMap: webWorker.executeWithFsMap.bind(webWorker),
renderUntilSettled: webWorker.renderUntilSettled.bind(webWorker),
getCircuitJson: webWorker.getCircuitJson.bind(webWorker),
clearEventListeners: comlinkWorker.clearEventListeners.bind(comlinkWorker),
execute: comlinkWorker.execute.bind(comlinkWorker),
executeWithFsMap: comlinkWorker.executeWithFsMap.bind(comlinkWorker),
renderUntilSettled: comlinkWorker.renderUntilSettled.bind(comlinkWorker),
getCircuitJson: comlinkWorker.getCircuitJson.bind(comlinkWorker),
on: (event: string, callback: (...args: any[]) => void) => {
const proxiedCallback = Comlink.proxy(callback)
webWorker.on(event, proxiedCallback)
comlinkWorker.on(event, proxiedCallback)
},
kill: async () => {
webWorker[Comlink.releaseProxy]()
comlinkWorker[Comlink.releaseProxy]()
rawWorker.terminate()
},
}
Expand Down
4 changes: 4 additions & 0 deletions lib/shared/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import type { AnyCircuitElement } from "circuit-json"
export interface WebWorkerConfiguration {
snippetsApiBaseUrl: string
cjsRegistryUrl: string
/**
* @deprecated, renamed to webWorkerBlobUrl
*/
webWorkerUrl?: URL | string
webWorkerBlobUrl?: URL | string
verbose?: boolean
}

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"scripts": {
"build": "bun run build:lib && bun run build:webworker && bun run build:blob-url",
"build:lib": "tsup-node ./lib/index.ts --format esm --sourcemap inline --dts -d dist/lib",
"build:webworker": "tsup ./webworker/index.ts --platform browser ./metadata.json --format esm --sourcemap inline -d dist/webworker",
"build:webworker": "tsup ./webworker/index.ts --platform browser --format esm --sourcemap inline -d dist/webworker",
"build:webworker:analyze": "tsup ./webworker/index.ts --platform browser --metafile ./metadata.json --format esm --sourcemap inline -d dist/webworker",
"build:blob-url": "bun run ./scripts/build-worker-blob-url.ts",
"format": "biome format --write .",
"format:check": "biome format ."
Expand Down
27 changes: 27 additions & 0 deletions tests/example6-dynamic-load-blob-url.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { createCircuitWebWorker } from "lib"
import { expect, test } from "bun:test"

// TODO should skip b/c uses network
test("example6-dynamic-load-blob-url", async () => {
const circuitWebWorker = await createCircuitWebWorker({})

await circuitWebWorker.execute(`
import { RedLed } from "@tsci/seveibar.red-led"
circuit.add(
<board width="10mm" height="10mm">
<RedLed name="LED1" />
</board>
)
`)

await circuitWebWorker.renderUntilSettled()

const circuitJson = await circuitWebWorker.getCircuitJson()

expect(circuitJson).toBeDefined()

const led = circuitJson.find((el: any) => el.name === "LED1")
expect(led).toBeDefined()
expect(led?.type).toBe("source_component")
})

0 comments on commit a7a1680

Please sign in to comment.