File size: 2,870 Bytes
1944112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
 * The Vite plugin, because one line of config you have to *remember* is one
 * line of config you will forget.
 *
 * ```js
 * import { everythingWebGPU } from "everything-webgpu/vite";
 * export default defineConfig({ plugins: [everythingWebGPU()] });
 * ```
 *
 * ## What it fixes, precisely
 *
 * The engine spawns its decode worker with
 * `new Worker(new URL("./engine-worker.js", import.meta.url), { type: "module" })`.
 * Vite's dependency pre-bundler runs esbuild over `node_modules` packages and
 * copies that expression through **verbatim** — but the copy now lives in
 * `node_modules/.vite/deps/everything-webgpu.js`, so `import.meta.url` points
 * there and the worker resolves to `.vite/deps/engine-worker.js`, which does not
 * exist. The real file is still at
 * `node_modules/everything-webgpu/src/engine/engine-worker.js`.
 *
 * Measured, not assumed. On a real (non-linked) install of this package:
 *
 * | | worker resolves | notes |
 * | --- | --- | --- |
 * | `vite build` | ✅ | Rollup handles it; output is byte-identical with or without this plugin |
 * | `vite dev`, excluded | ✅ | source served from `/@fs/`, `import.meta.url` is correct |
 * | `vite dev`, not excluded | ❌ 404 | the case this exists for |
 *
 * Two consequences worth stating, because both mislead:
 *
 *   1. **`vite build` never reproduces the bug.** A green production build is
 *      not evidence that the dev server works.
 *   2. **A linked (`file:`) dependency never reproduces it either**, because
 *      Vite does not pre-bundle linked packages. Every example in this repo is
 *      linked, so none of them can catch this — only a real install can. See
 *      `npm run verify-consumer`.
 *
 * The lazy `import("../../vendor/web-llm.js")` is *not* affected: esbuild
 * rewrites that one correctly to a hashed chunk. Only the worker breaks.
 *
 * If you would rather not add a plugin, the equivalent is:
 *
 * ```js
 * optimizeDeps: { exclude: ["everything-webgpu"] }
 * ```
 *
 * and if you do neither, `load()` fails with `PACKAGE_INCOMPLETE` naming this
 * fix rather than hanging on a worker that will never answer.
 */

/** The package's own name, so the exclusion cannot drift from it. */
const PACKAGE = "everything-webgpu";

/**
 * @param {{exclude?: string[]}} [opts] `exclude` adds further specifiers, for a
 *   host that re-exports this engine from its own package and hits the same
 *   pre-bundling of the worker URL.
 * @returns {import("vite").Plugin}
 */
export function everythingWebGPU({ exclude = [] } = {}) {
  return {
    name: "everything-webgpu",
    // `config` rather than `configResolved`: this has to merge into the user's
    // options before Vite computes the optimizer's entries, not after.
    config: () => ({
      optimizeDeps: { exclude: [PACKAGE, ...exclude] },
    }),
  };
}

export default everythingWebGPU;