Hello there, thanks for maintaining Nuxt and creating this wonderful module ❤️
I found some suspicious logs in my production app and therefore went on a deep dive with claude.
Description
src/plugins/transform.ts rewrites every CSS asset in generateBundle with transformCSS(..., { relative: true }), so a file like _nuxt/entry.<hash>.css ends up containing url(../_fonts/<hash>.woff2).
Browsers resolve url(...) against the stylesheet URL (/_nuxt/) and the font loads correctly. But any client that resolves it against the document URL instead -> crawlers, scanners, prefetchers, link-preview bots, anti-malware cache warmers computes a different path.
What we see
On a 2-segment dynamic page like /my/page/<product>/<id>, ../_fonts/<hash>.woff2 resolves to /my/page/_fonts/<hash>.woff2. That doesn't match Nitro's /_fonts/** public-asset handler, so the request falls through to the dynamic page route. The route calls another service with id=<hash>.woff2, gets 404, and the SSR throws a fatal H3Error -> once per font referenced, per request:
[fatal] [GET] /my/page/_fonts/k6j79xSGN8FY…ZaRgY.woff2
H3Error: Couldn't find Product with 'id'=k6j79xSGN8FY…ZaRgY.woff2
at [...]
This is steady-state in our production logs. The originating user-agents aren't browsers (those resolve correctly). They're a mix of bots/scanners that get CSS-relative URL resolution wrong.
Questions
- What's the motivation for the relative form?
publicAssetsURL() already handles base-URL / CDN prefixing on the SSR-inlined path - so the asymmetry between inlined CSS (absolute /_fonts/…) and bundled CSS (relative ../_fonts/…) is the part that surprised us.
- Would you accept an opt-out option (default unchanged) so we can switch our build to absolute URLs without patching the package?
- Or do you see this as something to handle application-side (e.g. a catch-all
/**/_fonts/** 404 handler)?
Happy to send a PR if (2) sounds right - just want to align on direction first. I already fiddled around with unit tests and a potential fix.
Hello there, thanks for maintaining Nuxt and creating this wonderful module ❤️
I found some suspicious logs in my production app and therefore went on a deep dive with claude.
Description
src/plugins/transform.tsrewrites every CSS asset in generateBundle withtransformCSS(..., { relative: true }), so a file like_nuxt/entry.<hash>.cssends up containingurl(../_fonts/<hash>.woff2).Browsers resolve
url(...)against the stylesheet URL(/_nuxt/)and the font loads correctly. But any client that resolves it against the document URL instead -> crawlers, scanners, prefetchers, link-preview bots, anti-malware cache warmers computes a different path.What we see
On a 2-segment dynamic page like
/my/page/<product>/<id>,../_fonts/<hash>.woff2resolves to/my/page/_fonts/<hash>.woff2. That doesn't match Nitro's/_fonts/**public-asset handler, so the request falls through to the dynamic page route. The route calls another service withid=<hash>.woff2, gets 404, and the SSR throws a fatal H3Error -> once per font referenced, per request:This is steady-state in our production logs. The originating user-agents aren't browsers (those resolve correctly). They're a mix of bots/scanners that get CSS-relative URL resolution wrong.
Questions
publicAssetsURL()already handles base-URL / CDN prefixing on the SSR-inlined path - so the asymmetry between inlined CSS (absolute/_fonts/…) and bundled CSS (relative../_fonts/…) is the part that surprised us./**/_fonts/**404 handler)?Happy to send a PR if (2) sounds right - just want to align on direction first. I already fiddled around with unit tests and a potential fix.