Skip to content

CSS-only entrypoint sometimes resolves to a .js file in the manifest under Vite 8 / Rolldown #615

Description

@s-faychatelard

Environment

  • vite_ruby: 3.10.2
  • vite_rails: 3.11.0
  • Vite: 8.x (using the Rolldown bundler)

Description

This only affects production-style builds that read from the manifest. In dev mode, Vite serves the raw source file directly and transforms it into CSS on request, and resolve_entries deliberately returns no stylesheets while the dev server is running (CSS is expected to arrive via the JS module graph's HMR client instead) — so a standalone CSS entrypoint like this one has to be rendered differently in dev vs. production anyway, and the bug below only shows up on the production/manifest path.

For a CSS-only entrypoint (e.g. assets/stylesheets/foo.scss), ViteRuby::Manifest#resolve_entries(entry_name, type: :stylesheet) is inconsistent about where the actual stylesheet ends up in the manifest, depending on the entrypoint:

  • For some CSS-only entrypoints, the manifest's file key for the entry is the real .css file, as expected.
  • For others, file is a .js wrapper (seemingly a Rolldown artifact), and the real stylesheet only shows up in the entry's css array.

Since vite_stylesheet_tag (and resolve_entries(..., type: :stylesheet)'s scripts result) only reads the file key, this means some CSS-only entrypoints are rendered as (broken) <script>/stylesheet tags pointing at a .js file instead of the actual CSS, unless the caller also inspects the css array and merges it in manually.

Current workaround

We're working around this in our own helper by manually reading both scripts and stylesheets from resolve_entries and merging them:

entries = ViteRuby.instance.manifest.resolve_entries(entry_name, type: :stylesheet)
own_file = entries.fetch(:scripts).first
stylesheets = entries.fetch(:stylesheets)
stylesheets = [own_file, *stylesheets] if own_file&.end_with?('.css')
stylesheet_link_tag(*stylesheets.uniq, media: 'all', rel: 'stylesheet')

This was added while upgrading to Vite 8 in our app. We'd like to drop it once the manifest resolution is fixed/normalized upstream so vite_stylesheet_tag can be used directly again.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug: pending triageSomething doesn't seem to be working, but hasn't been verified

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions