Skip to content

Bundled CSS emits url(../_fonts/…)-404 cascades when non-browser clients resolve those URLs against the document path #829

@PatrikBird

Description

@PatrikBird

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

  1. 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.
  2. Would you accept an opt-out option (default unchanged) so we can switch our build to absolute URLs without patching the package?
  3. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions