cloudflare / cloudflare/workers-sdk
Workers & Routes & SPAs - assets not resolving
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.5k
- Avg merge
- 3d 8h
- Merged PRs (30d)
- 186
Description
### What versions & operating system are you using?
Node 22, wrangler4.22, viteplugin: 1.7.5
### Please provide a link to a minimal reproduction
_No response_
### Describe the Bug
I have a worker, using Vite plugin, and it is bound to route: `*.domain.com/auth/*`. Note the sub-path, that's the key issue here.
In vite, my base is set to : /auth/
wrangler asset config:
```
"assets": {
"not_found_handling": "single-page-application",
"run_worker_first": ["/auth/api/*"],
"html_handling": "drop-trailing-slash"
},
```
My dist folder after build:
```
├── auth_svc
│ ├── assets
│ │ ├── bun-sqlite-dialect-BA34DVYO.js
│ │ ├── index-DS8CXNKO.js
│ │ └── server.edge-CMi7F8Zj.js
│ ├── index.js
│ └── wrangler.json
└── client
├── assets
│ ├── index-C6_7OQDu.js
│ └── etc....
├── images
│ └── favicon.ico
├── index.html
└── manifest.json
```
Cloudflare will correctly invoke my worker only when the route matches, ie, a url with `/auth/*`, however, the app is "mounted" at the root `/`, which creates a conflict that is tricky to solve.
With the config above, we get:
✅ curl test.domain.com/auth/login - OK - returns index.html page
✅ curl test.domain.com/auth/api - OK, worker gets invoked successfully
❓ the index.html file has the following:
- public urls: ``
- chunks: ``
❌ curl https://test.domain.com/auth/images/favicon.ico - returns index.html ( from public folder)
❌ curl https://test.domain.com/auth/assets/index-C6_7OQDu.js - returns index.html page (bundled assets)
The requests fail because the files are actually not under `/auth`, but under `/`. the `dist/client` folder is mounted to `/`.
We can proove this by
## Attempt 1
.. adding this to the vite config:
```
build: {
assetsDir: 'auth/assets'
}
```
now, `dist` builds like this:
```
./dist
├── auth_svc
│ └── auth
│ └── assets
└── client
├── auth
│ └── assets
└── images
```
and these now work:
https://test.domain.com/auth/images/favicon.ico
https://test.domain.com/auth/assets/index-C6_7OQDu.js
but we have a different problem; the index.html page has bad URLs:
- public URLs are OK: `<link rel="icon" href="/auth/images/favicon.ico" />`
- chunks are not: `<script type="module" crossorigin src="/auth/auth/assets/index-C6_7OQDu.js" />`
## Attempt 2
Another attempt to fix this with Vite is using an experimental config that gives you full control over the URLs generated:
```
build: {
assetsDir: 'auth/assets'
},
experimental: {
renderBuiltUrl(filename, { hostId, hostType, type }) {
if (type === 'public') {
return `/auth/${filename}`;
}
return `/${filename}`;
},
},
```
This produces:
- ✅ file system ( dist/client/auth )
- ❌ public import URLS:
` <link rel="apple-touch-icon" sizes="180x180" href="/auth/images/apple-touch-icon.png">`
- ✅ chunk import URLS
We could fix this by editing the original index.html and hard coding the /auth prefix there, but not clean.
## Attempt 3
Looking deeper into the plugin code, at how it builds the output paths:
https://github.com/cloudflare/workers-sdk/blob/main/packages/vite-plugin-cloudflare/src/utils.ts#L10-L20
We can see that maybe we can set the outDir for the environment:
```
environments: {
client: {
build: {
outDir: 'dist/client/auth/'
}
}
},
```
This gives us:
- ✅ file system ( dist/client/auth )
- ✅ public imports (they start with /auth), ex: ` <link rel="icon" href="/auth/images/favicon.ico" />`
- ✅ chunk imports (start with /auth/assets) ex: <script type="module" crossorigin src="/auth/assets/index-C6_7OQDu.js">
but..
- ❌ wrong `assets.directory` in the generated wrangler config: ` "directory": "../client/auth"`.
The wrangler assets.directory should've remained `../client` to make everything work.
## TLDR
There is no clean way to align the following:
- Vite `base` setting
- Vite build folder structure
- Wrangler assets.directory
IMO, the correct thing to do would be to have the Vite plugin respect the `base` config, and append that to the build output, but keep the assets.directory as `client`
### Please provide any relevant error logs
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.