qwikVite: make Vite config the single source of truth for asset paths (stop overriding assetFileNames)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 22.1k
- Forks
- 1.4k
- Avg merge
- 1d 10h
- Merged PRs (30d)
- 52
Description
Problem
qwikVite overrides Rollup's output.assetFileNames (to assets/[hash]-[name]) in addition to forcing JS chunks into build/. Because it overrides asset paths, standard Vite options like build.assetsDir don't flow through the way users expect, and qwikVite has to special-case assetsDir itself.
That special-casing is applied client-only (useAssetsDir = target === 'client' in packages/qwik-vite/src/plugins/vite.ts). So with build.assetsDir set, the client and SSR builds disagree on the asset URL: the client chunk emits /q/… but the SSR-rendered HTML emits /assets/… while the file is actually at /q/… → 404 on first paint, before the client resumes.
Proposal — make Vite config the single source of truth
qwikVite should keep only its one real opinion — JS chunks live at build/ (the preloader's fixed home) — and otherwise read the Vite config instead of overriding paths:
- Keep
chunkFileNames/entryFileNamesforced tobuild/…(with??=so a user can still override). - Stop setting
assetFileNames. Assets become 100% native Vite/Rolldown, sobuild.assetsDir(andbase) just work — identically on client and SSR.
This is exactly how qwik-bundler already does it: src/build/chunking.ts's outputDefaults() sets only chunk/entry names, and assetFileNames / assetsDir appear nowhere in the source.
Evidence
Prototyped against current v2 qwikVite by deleting the assetFileNames override block. Emitted <img src> for a ?url asset:
| config | client src |
SSR src |
on disk | chunks |
|---|---|---|---|---|
| default | /assets/circle-…svg |
/assets/circle-…svg |
dist/assets/ |
dist/build |
build.assetsDir: 'q' |
/q/circle-…svg |
/q/circle-…svg |
dist/q/ |
dist/build |
build.assetsDir now relocates assets consistently on client + SSR — the 404 disappears, because it was caused purely by the client-only override. Users who want a nested assets/ subfolder can still set output.assetFileNames directly (native Rollup, no Qwik involvement).
The work
- Plugin: read the resolved Vite config as the source of truth — drop the
assetFileNamesoverride and theuseAssetsDir/_astrospecial-case; keep chunks atbuild/. - CLI: a
create-qwikcodemod to migrate any existing Qwik-specific options over to their regular Vite config keys, so current projects move over cleanly.
Scope / notes
- Default asset filenames change from
[hash]-[name]to Vite's native[name]-[hash](cosmetic). - Router: with
build.assetsDirnatively relocating assets again,@qwik.dev/routerneeds to stayassetsDir-aware forisStaticPathand the Cloudflare_routes.jsonexclude — the direction of #8811, adjusted for the fact that chunks stay atbuild/while assets move to<assetsDir>/.
Refs: #8811, #8817 (an initial attempt that instead removed build.assetsDir support while still overriding asset paths — wrong direction, superseded by this).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read packages/qwik-vite/src/plugins/vite.ts and compare its output settings with the referenced qwik-bundler src/build/chunking.ts outputDefaults(). Reproduce the client/SSR assetDir matrix from the issue, then trace the create-qwik codemod and the router changes described in the scope. Done means assets follow Vite config consistently, chunks remain in build/, and existing Qwik options have a migration path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript, vite
- Domain
- build-system, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100