mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
# What Closes https://github.com/vercel/next.js/issues/84782 Closes https://github.com/vercel/next.js/issues/74842 Closes https://github.com/vercel/next.js/issues/82520 Closes PACK-3723 Replace blob URLs for web workers with real entrypoint files, fixing relative URL resolution inside workers. Implements support for `SharedWorkers` since it's now a simple variation of the `Worker` case. Note that all generated files (and shared-worker querystrings) are appropriately content-hashed and do not rely on deployment IDs and will work w/immutable resources. # Why Workers created via `new Worker(new URL('./worker.js', import.meta.url))` previously got blob URLs. This breaks relative URL resolution inside workers - WASM imports like `new URL('./file.wasm', import.meta.url)` fail because `import.meta.url` returns `blob:http://...` instead of a real path. # How We emit a real worker entrypoint file instead of blob URLs. The entrypoint reads bootstrap config from URL hash params (`#params=....`), then loads the worker's chunks via `importScripts`. The `ChunkingContext` trait gets a new `worker_entrypoint()` method returning a singleton bootstrap asset. Node.js `bail!`s for now but could implement its own in the future. The browser implementation (`EcmascriptBrowserWorkerEntrypoint`) compiles and minifies `worker-entrypoint.ts`, which parses `#params={globals,chunks}` from the URL at runtime. `WorkerLoaderChunkItem` now emits `__turbopack_worker_url__(entrypoint, chunks, shared)` instead of the old blob URL shim. SharedWorker passes `shared=true` which adds a querystring - the browser handles worker identity via URL, so same URL means same instance. Generated code changes (pseudocode): ```javascript __turbopack_export_value__(__turbopack_worker_blob_url__(["chunk1.js", "chunk2.js"])); ``` After: ```javascript __turbopack_export_value__(__turbopack_worker_url__("worker-entrypoint.js", ["chunk1.js", "chunk2.js"], false)); ``` # Notes Webpack doesn't currently correctly support `SharedWorkers`. The e2e test behaves properly in turbopack after this change, but webpack spins up two separate workers where it should only be spinning up one. I generated snapshot tests for workers in the first and last commits to help understand the generated code better. # Testing - Snapshot tests for Worker, SharedWorker, and minified output - E2E tests for WASM loading in workers (`test/e2e/app-dir/worker/`)
40 lines
1.0 KiB
JavaScript
40 lines
1.0 KiB
JavaScript
'use client'
|
|
import { useState } from 'react'
|
|
|
|
export default function Home() {
|
|
const [state, setState] = useState('default')
|
|
return (
|
|
<div>
|
|
<button
|
|
onClick={() => {
|
|
const worker = new SharedWorker(
|
|
new URL('../shared-worker', import.meta.url),
|
|
{
|
|
type: 'module',
|
|
}
|
|
)
|
|
worker.port.addEventListener('message', (event) => {
|
|
setState(event.data)
|
|
// Run a second time, which will use the same worker
|
|
const worker = new SharedWorker(
|
|
new URL('../shared-worker', import.meta.url),
|
|
{
|
|
type: 'module',
|
|
}
|
|
)
|
|
worker.port.addEventListener('message', (event) => {
|
|
setState(event.data)
|
|
})
|
|
worker.port.start()
|
|
})
|
|
worker.port.start()
|
|
}}
|
|
>
|
|
Get web worker data
|
|
</button>
|
|
<p>Worker state: </p>
|
|
<p id="worker-state">{state}</p>
|
|
</div>
|
|
)
|
|
}
|