rails / cssbundling-rails

Bundle and process CSS in Rails with Tailwind, PostCSS, and Sass via Node.js.
MIT License
563 stars 83 forks source link

Sprockets error when using additional CSS files #117

Closed olivier-thatch closed 1 year ago

olivier-thatch commented 1 year ago

The README says:

you should also consider simply referring to your other CSS files directly, instead of bundling them all into one big file. It's better for caching, and it's simpler to setup. You can refer to other CSS files by expanding the stylesheet_link_tag in application.html.erb like so: <%= stylesheet_link_tag "application", "other", "styles", "data-turbo-track": "reload" %>.

Here's what I did:

  1. Create a new Rails app with rails new my_app -j esbuild --css tailwind
  2. Create a new CSS file app/assets/stylesheets/foo.css
  3. Change the stylesheet_link_tag in application.html.erb like so: <%= stylesheet_link_tag "application", "foo", "data-turbo-track": "reload" %>

This causes a Sprockets::Rails::Helper::AssetNotPrecompiledError exception with the following error message:

Asset `more.css` was not declared to be precompiled in production.
Declare links to your assets in `app/assets/config/manifest.js`.

  //= link foo.css

and restart your server

I can fix the error by editing manifest.js to include the additional stylesheet, e.g. with //= link_directory ../stylesheets .css, but is this the correct approach? The cssbundling-rails gem explicitly removes this line from manifest.js as part of its install task: https://github.com/rails/cssbundling-rails/blob/0d06deae6632d5b2c2789a61b30617a7e563a066/lib/install/install.rb#L8-L9

I realize this is probably more of an issue with Sprockets rather than with cssbundling-rails itself, but the boundary's not very clear. What is the correct approach to add additional CSS files when using cssbundling-rails?

  1. Re-add //= link_directory ../stylesheets .css to manifest.js?
  2. Add only the additional CSS files, e.g. with //= link ../stylesheets/foo.css?
  3. Something else?
piotrmurach commented 1 year ago

Hi @olivier-thatch

I agree that the boundary between cssbundling-rails and sprockets in Rails 7 is a bit confusing. Hopefully, I can clear up some things as I don't believe that there is anything wrong with how Sprockets work.

Essentially, the cssbundilng-rails is letting you choose how you want to bundle your CSS. In doing so, it leaves it up to you how you want to configure your additional stylesheets. I'll demonstrate my point with my preferred option the sass preprocessor (this will differ for tailwind but conceptually is the same).

For example, when using sass you have to specify any stylesheets that you want to get compiled into the app/assets/build directory. In other words, the sprockets no longer handles how you compile and how many entry points for your CSS you have but sass does. A simple hypothetical command that you could run via package.json script would be:

sass ./app/assets/styelsheets/foo.sass.scss:./app/assets/build/foo.css .../build/application.css

This would produce both application.css and foo.css in the app/assets/build directory. You would write an equivalent configuration in the tailwind.config.js.

Then when you render <%= stylesheet_link_tag "application", "foo" %> in your layout, the asset pipeline handled by sprockets will automatically pick up the exported foo.css from the build directory. You don't have to modify the manifest.js configuration for that to happen unless you wish to add a new directory to the asset pipeline.

Another approach you can consider is even removing cssbundling-rails and using only esbuild to deal with your JS and CSS. Then I can imagine that a esbuild-plugin-tailwindcss could handle your CSS bundling needs.

Given all the above, I believe this is not an issue with either cssbundling-rails or sprockets. I hope this helps.