cloudflare / cloudflare/workers-sdk
@cloudflare/vite-plugin - WASM files incorrectly bundled into server assets with TanStack Start + Cloudflare Workers
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.5k
- Avg merge
- 3d 8h
- Merged PRs (30d)
- 187
Description
### What versions & operating system are you using?
System:
OS: Windows 11 10.0.26200
CPU: (12) x64 AMD Ryzen 5 5500U with Radeon Graphics
Memory: 4.41 GB / 15.34 GB
Binaries:
Node: 26.5.1 - C:\Program Files\nodejs\node.EXE
npm: 11.12.1 - C:\Program Files\nodejs\npm.CMD
bun: 1.3.14 - C:\Users\Probi\.bun\bin\bun.EXE
npmPackages:
@cloudflare/vite-plugin: ^1.50.0 => 1.50.0
wrangler: ^4.118.0 => 4.118.0
### Please provide a link to a minimal reproduction
https://github.com/probir-sarkar/browserstay/tree/issue/jsquash
### Describe the Bug
```
bun run build
ls dist/client/assets/*.wasm # expected
ls dist/server/assets/*.wasm # BUG: identical files present
```
TanStack Start (SSR) copies Web Worker WASM binaries into dist/server/assets, inflating the worker bundle with ~9 MB of dead code — wasm should only ship in the client build.
When building a TanStack Start app that uses a Web Worker which imports @jsquash/* image codecs (which ship Emscripten-compiled .wasm files), the SSR/server build also emits all the WASM binaries plus the full worker chunk into dist/server/assets/.
The new URL(..., import.meta.url) worker pattern is resolved by Vite into every environment's module graph (both the client and ssr environments). TanStack Start's SSR build therefore bundles image.worker.ts and its @jsquash/* imports, emitting the worker chunk + WASM assets into dist/server/assets/.
Notably, clawpdf (which also ships a large pdfium.esm.wasm) does not leak — because it is imported via the client-only clawpdf/browser entry, so the server never pulls its worker/wasm graph. The leak is specific to code that is reachable from the SSR graph even though it only ever executes in a browser worker.
As a control, the **same app** (same routes, same `image.worker.ts`, same `@jsquash/*` imports) built with **Nitro** (via `@tanstack/react-start`'s Nitro adapter) does **not** leak WASM into the server output:
### Please provide any relevant error logs
$ bun run build
$ vite build && tsc --noEmit
(node:13632) [DEP0205] DeprecationWarning: `module.register()` is deprecated. Use `module.registerHooks()` instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
vite v8.2.0 building client environment for production...
[plugin rolldown:vite-resolve] Module "node:zlib" has been externalized for browser compatibility, imported by "D:/toolbox/node_modules/clawpdf/dist/png.js". See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.
[plugin rolldown:vite-resolve] Module "node:fs/promises" has been externalized for browser compatibility, imported by "D:/toolbox/node_modules/clawpdf/dist/input.js". See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.
[plugin rolldown:vite-resolve] Module "node:url" has been externalized for browser compatibility, imported by "D:/toolbox/node_modules/clawpdf/dist/input.js". See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.
[plugin rolldown:vite-resolve] Module "module" has been externalized for browser compatibility, imported by "D:/toolbox/node_modules/clawpdf/dist/vendor/pdfium.esm.js". See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.
✓ 2916 modules transformed.
computing gzip size...
dist/client/.assetsignore 0.02 kB
dist/client/assets/avif_enc_mt.worker-BSwsqSX3.js 28.17 kB
dist/client/assets/webp_dec-C990n7mh.wasm 137.96 kB │ gzip: 50.00 kB
dist/client/assets/mozjpeg_dec-muSO2n8T.wasm 166.47 kB │ gzip: 64.57 kB
dist/client/assets/image.worker-DDVYh5u9.js 174.50 kB
dist/client/assets/squoosh_png_bg-DAY7U9NW.wasm 181.08 kB │ gzip: 85.73 kB
dist/client/assets/mozjpeg_enc-DO-zoExo.wasm 251.52 kB │ gzip: 60.44 kB
dist/client/assets/webp_enc-BpZvKflB.wasm 281.26 kB │ gzip: 115.98 kB
dist/client/assets/webp_enc_simd-CFvKQ_80.wasm 345.58 kB │ gzip: 128.61 kB
dist/client/assets/avif_dec-B7YOdlSS.wasm 1,170.93 kB │ gzip: 344.65 kB
dist/client/assets/avif_enc-Co4TcJko.wasm 3,485.87 kB │ gzip: 1,136.17 kB
dist/client/assets/avif_enc_mt-DFoVXd45.wasm 3,534.66 kB │ gzip: 1,150.16 kB
dist/client/assets/pdfium.esm-CbcxY23o.wasm 3,984.25 kB │ gzip: 2,037.38 kB
dist/client/assets/globals-DD8m-uJz.css 133.07 kB │ gzip: 19.66 kB
dist/client/assets/owner-NnnQFEU-.js 0.06 kB │ gzip: 0.07 kB
dist/client/assets/__vite-browser-external-2W3EstLn.js 0.10 kB │ gzip: 0.11 kB
dist/client/assets/isElementDisabled-KSuuBj8D.js 0.11 kB │ gzip: 0.11 kB
dist/client/assets/loader-circle-CFsmICVq.js 0.13 kB │ gzip: 0.14 kB
dist/client/assets/serializeValue-B_EucO5O.js 0.13 kB │ gzip: 0.12 kB
dist/client/assets/upload-WXTY7sBC.js 0.21 kB │ gzip: 0.18 kB
dist/client/assets/services-BXJRwWis.js 0.22 kB │ gzip: 0.18 kB
dist/client/assets/circle-alert--pPuBEdh.js 0.23 kB │ gzip: 0.17 kB
dist/client/assets/typeof-B5XbjTb1.js 0.27 kB │ gzip: 0.16 kB
dist/client/assets/refresh-cw-B8oFrnvQ.js 0.30 kB │ gzip: 0.21 kB
dist/client/assets/mail-Be0RXyIx.js 0.31 kB │ gzip: 0.24 kB
dist/client/assets/trash-2-BjOoI-HM.js 0.31 kB │ gzip: 0.20 kB
dist/client/assets/file-text-DhezXSxX.js 0.37 kB │ gzip: 0.24 kB
dist/client/assets/hammer-CI3f9uwG.js 0.38 kB │ gzip: 0.26 kB
dist/client/assets/shadowDom-6ckEgmCV.js 0.40 kB │ gzip: 0.26 kB
dist/client/assets/zip-nwiPIsHA.js 0.55 kB │ gzip: 0.34 kB
dist/client/assets/useAriaLabelledBy-Cy8K8d1z.js 0.57 kB │ gzip: 0.38 kB
dist/client/assets/rolldown-runtime-hePW80VL.js 0.71 kB │ gzip: 0.42 kB
dist/client/assets/CSPContext-BdFjUw3J.js 0.97 kB │ gzip: 0.57 kB
dist/client/assets/badge-Bz0G4vqP.js 1.40 kB │ gzip: 0.64 kB
dist/client/assets/trust-bar-TLaKthze.js 1.45 kB │ gzip: 0.78 kB
dist/client/assets/with-selector-BM4Rcpsn.js 1.67 kB │ gzip: 0.74 kB
dist/client/assets/hooks-DGUKDrkD.js 1.76 kB │ gzip: 0.81 kB
dist/client/assets/pretty-bytes-DlqFe0lJ.js 1.80 kB │ gzip: 0.90 kB
dist/client/assets/image-tools-CC-uO7rE.js 2.36 kB │ gzip: 0.92 kB
dist/client/assets/pdf-tools-BfA6X6cX.js 2.38 kB │ gzip: 0.93 kB
dist/client/assets/input-DJT1K7K8.js 2.44 kB │ gzip: 1.25 kB
dist/client/assets/drop-zone-tvplLLJu.js 2.59 kB │ gzip: 1.23 kB
dist/client/assets/useValueChanged-CUvb65Zg.js 3.49 kB │ gzip: 1.42 kB
dist/client/assets/useCompositeItem-NsoGINfq.js 4.11 kB │ gzip: 1.85 kB
dist/client/assets/switch-DXmUCMuj.js 4.42 kB │ gzip: 2.00 kB
dist/client/assets/image.client-CjgJwQ5n.js 4.73 kB │ gzip: 1.98 kB
dist/client/assets/useLabelableId-o6kz9kuv.js 4.80 kB │ gzip: 1.97 kB
dist/client/assets/use-immer.module-D3wpjD-7.js 9.28 kB │ gzip: 3.80 kB
dist/client/assets/image-converter-DgcKrvYR.js 9.50 kB │ gzip: 3.64 kB
dist/client/assets/image-compressor-0J3I7a4a.js 10.07 kB │ gzip: 3.69 kB
dist/client/assets/merge-pdf-CdXkMyOY.js 10.63 kB │ gzip: 3.99 kB
dist/client/assets/routes-G1FJZqrG.js 10.76 kB │ gzip: 3.49 kB
dist/client/assets/image-resize-BGzL7FYs.js 11.00 kB │ gzip: 4.11 kB
dist/client/assets/pdf-to-image-HZm0DqGE.js 11.17 kB │ gzip: 4.31 kB
dist/client/assets/browser-D-PHLAgM.js 11.48 kB │ gzip: 5.64 kB
dist/client/assets/common-Dj_k2Bz4.js 18.36 kB │ gzip: 7.13 kB
dist/client/assets/slider-CMNtKBvW.js 19.54 kB │ gzip: 7.71 kB
dist/client/assets/browser-Bg25_sDh.js 23.47 kB │ gzip: 8.86 kB
dist/client/assets/purify.es-1EvBSpuh.js 24.49 kB │ gzip: 9.56 kB
dist/client/assets/password-generator-C9zLPM3-.js 24.81 kB │ gzip: 9.29 kB
dist/client/assets/qr-generator-DY7Z1c3F.js 26.57 kB │ gzip: 8.59 kB
dist/client/assets/select-D2uC7ypr.js 30.15 kB │ gzip: 10.93 kB
dist/client/assets/usePositioner-B80JBSqh.js 54.16 kB │ gzip: 19.60 kB
dist/client/assets/card-DkRrRv4M.js 54.34 kB │ gzip: 18.34 kB
dist/client/assets/sortable-DMElmqOm.js 110.34 kB │ gzip: 35.84 kB
dist/client/assets/pdf-DfZEJyoA.js 137.66 kB │ gzip: 39.36 kB
dist/client/assets/index.es-DH1ipSb3.js 151.31 kB │ gzip: 48.88 kB
dist/client/assets/html2canvas-CA7kyov8.js 199.49 kB │ gzip: 46.77 kB
dist/client/assets/image-to-pdf-CCeZ2XII.js 403.57 kB │ gzip: 130.80 kB
dist/client/assets/es-C8kTfHMH.js 424.89 kB │ gzip: 177.41 kB
dist/client/assets/index-DMeWptg0.js 425.55 kB │ gzip: 133.71 kB
dist/client/assets/split-pdf-C_0EK33s.js 436.73 kB │ gzip: 130.01 kB
✓ built in 1.78s
vite v8.2.0 building ssr environment for production...
✓ 2300 modules transformed.
computing gzip size...
dist/server/wrangler.json 1.29 kB │ gzip: 0.66 kB
dist/server/.vite/manifest.json 9.03 kB │ gzip: 1.28 kB
dist/server/assets/avif_enc_mt.worker-BSwsqSX3.js 28.17 kB
dist/server/assets/webp_dec-C990n7mh.wasm 137.96 kB │ gzip: 50.00 kB
dist/server/assets/mozjpeg_dec-muSO2n8T.wasm 166.47 kB │ gzip: 64.57 kB
dist/server/assets/image.worker-DDVYh5u9.js 174.50 kB
dist/server/assets/squoosh_png_bg-DAY7U9NW.wasm 181.08 kB │ gzip: 85.73 kB
dist/server/assets/mozjpeg_enc-DO-zoExo.wasm 251.52 kB │ gzip: 60.44 kB
dist/server/assets/webp_enc-BpZvKflB.wasm 281.26 kB │ gzip: 115.98 kB
dist/server/assets/webp_enc_simd-CFvKQ_80.wasm 345.58 kB │ gzip: 128.61 kB
dist/server/assets/avif_dec-B7YOdlSS.wasm 1,170.93 kB │ gzip: 344.65 kB
dist/server/assets/avif_enc-Co4TcJko.wasm 3,485.87 kB │ gzip: 1,136.17 kB
dist/server/assets/avif_enc_mt-DFoVXd45.wasm 3,534.66 kB │ gzip: 1,150.16 kB
dist/server/assets/globals-DD8m-uJz.css 133.07 kB │ gzip: 19.66 kB
dist/server/assets/start-5Z2QO8AU.js 0.14 kB │ gzip: 0.13 kB
dist/server/assets/empty-plugin-adapters-D9UWiqvJ.js 0.22 kB │ gzip: 0.16 kB
dist/server/assets/hammer-foCtYLGa.js 0.66 kB │ gzip: 0.42 kB
dist/server/assets/mail-CbzGYPLj.js 0.79 kB │ gzip: 0.39 kB
dist/server/assets/palette-Dphdfq4p.js 0.85 kB │ gzip: 0.42 kB
dist/server/assets/badge-CZCRVk3x.js 1.82 kB │ gzip: 0.83 kB
dist/server/assets/trust-bar-XEwBN1do.js 2.75 kB │ gzip: 1.12 kB
dist/server/assets/image-to-pdf-0BmyndT3.js 2.84 kB │ gzip: 1.13 kB
dist/server/assets/image-resize-Cz1kUD1r.js 3.17 kB │ gzip: 1.32 kB
dist/server/assets/hooks-RLPIEwXK.js 3.20 kB │ gzip: 0.98 kB
dist/server/assets/image-compressor-BKIaMalc.js 3.21 kB │ gzip: 1.32 kB
dist/server/assets/password-generator-BPUvH90H.js 3.25 kB │ gzip: 1.23 kB
dist/server/assets/image-converter-Du9lcFwH.js 3.26 kB │ gzip: 1.27 kB
dist/server/assets/qr-generator-CcWpMpz_.js 3.43 kB │ gzip: 1.39 kB
dist/server/assets/faq-section-Zx_pYCwt.js 3.81 kB │ gzip: 1.11 kB
dist/server/assets/pdf-tools-DWsR9HnR.js 4.03 kB │ gzip: 1.22 kB
dist/server/assets/image-tools-B_g3lSYg.js 4.05 kB │ gzip: 1.22 kB
dist/server/assets/split-pdf-0dH2r3g1.js 6.10 kB │ gzip: 1.95 kB
dist/server/assets/_tanstack-start-manifest_v-BqH9Yi0T.js 6.22 kB │ gzip: 1.27 kB
dist/server/assets/site-BfTsAHjR.js 6.79 kB │ gzip: 1.95 kB
dist/server/assets/merge-pdf-DqSYJ68A.js 6.80 kB │ gzip: 2.29 kB
dist/server/assets/link-DBMHWm_O.js 8.27 kB │ gzip: 2.69 kB
dist/server/assets/routes-D6ZsoboU.js 17.14 kB │ gzip: 4.33 kB
dist/server/assets/react-dom-BwOCpxiD.js 26.26 kB │ gzip: 6.80 kB
dist/server/assets/pdf-to-image-DJEyb8xD.js 26.65 kB │ gzip: 7.90 kB
dist/server/assets/common-DyBxDLsH.js 50.31 kB │ gzip: 12.21 kB
dist/server/assets/useStore-bEagTgYF.js 50.34 kB │ gzip: 13.51 kB
dist/server/assets/Match-D2Fo24Tl.js 109.54 kB │ gzip: 26.33 kB
dist/server/assets/card-Gqaf4sce.js 129.73 kB │ gzip: 27.26 kB
dist/server/assets/router-Ddc-7bjg.js 456.90 kB │ gzip: 97.93 kB
dist/server/index.js 619.24 kB │ gzip: 128.85 kB
✓ built in 1.00s
[prerender] Prerendering pages...
[prerender] Concurrency: 14
[prerender] Crawling: /
[prerender] Crawling: /image-compressor
[prerender] Crawling: /image-converter
[prerender] Crawling: /image-resize
[prerender] Crawling: /image-to-pdf
[prerender] Crawling: /image-tools
[prerender] Crawling: /merge-pdf
[prerender] Crawling: /password-generator
[prerender] Crawling: /pdf-to-image
[prerender] Crawling: /pdf-tools
[prerender] Crawling: /qr-generator
[prerender] Crawling: /split-pdf
GET /image-compressor/ 307 Temporary Redirect (7ms)
GET /image-converter/ 307 Temporary Redirect (6ms)
GET / 200 OK (119ms)
GET /image-resize/ 307 Temporary Redirect (6ms)
GET /image-to-pdf/ 307 Temporary Redirect (5ms)
GET /image-tools/ 307 Temporary Redirect (6ms)
GET /merge-pdf/ 307 Temporary Redirect (6ms)
GET /password-generator/ 307 Temporary Redirect (5ms)
GET /pdf-to-image/ 307 Temporary Redirect (5ms)
GET /pdf-tools/ 307 Temporary Redirect (6ms)
GET /qr-generator/ 307 Temporary Redirect (5ms)
GET /split-pdf/ 307 Temporary Redirect (5ms)
GET /image-converter 200 OK (17ms)
GET /image-compressor 200 OK (13ms)
GET /image-resize 200 OK (11ms)
GET /image-to-pdf 200 OK (10ms)
GET /image-tools 200 OK (10ms)
GET /merge-pdf 200 OK (13ms)
GET /password-generator 200 OK (10ms)
GET /pdf-to-image 200 OK (12ms)
GET /pdf-tools 200 OK (9ms)
GET /qr-generator 200 OK (10ms)
GET /split-pdf 200 OK (10ms)
[prerender] Prerendered 12 pages:
[prerender] - /image-converter
[prerender] - /image-compressor
[prerender] - /image-resize
[prerender] - /image-tools
[prerender] - /image-to-pdf
[prerender] - /merge-pdf
[prerender] - /pdf-tools
[prerender] - /password-generator
[prerender] - /
[prerender] - /pdf-to-image
[prerender] - /qr-generator
[prerender] - /split-pdf
[sitemap] Building Sitemap...
[sitemap] Writing sitemap XML at dist\client\sitemap.xml
[sitemap] Writing pages data at dist\client\pages.json
Contributor guide
Research direction
Start with the linked browserstay reproduction and run `bun run build`; compare the `dist/client/assets` and `dist/server/assets` outputs. Trace how `image.worker.ts` and its `@jsquash/*` imports enter the TanStack Start SSR graph through `@cloudflare/vite-plugin`, using the Nitro build as a control. Done means the worker and WASM assets remain in the client output without being emitted into server assets.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript, vite, wasm
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100