ElMassimo / ElMassimo/vite_ruby
CSS-only entrypoint sometimes resolves to a `.js` file in the manifest under Vite 8 / Rolldown
- Dominant language
- Ruby
- Stars
- 1.6k
- Forks
- 149
- Avg merge
- 5h 13m
- Merged PRs (30d)
- 2
Description
### 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) ``/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:
```ruby
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.
Contributor guide
Research direction
Start at ViteRuby::Manifest#resolve_entries(entry_name, type: :stylesheet) and the production manifest path used by vite_stylesheet_tag. Reproduce with a CSS-only entrypoint under Vite 8/Rolldown, then verify that resolution consistently returns the actual stylesheet rather than a .js wrapper, including when the stylesheet appears in the manifest's css array.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rails, ruby, vite
- Domain
- build-system
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100