I have a project where each page needs to import an extra css or JS file for only that page. Is it a good practise to use a different layout file for each view? (I don't want my view files to contain references to css/JS files).
I mean i can have a different layout for each view but i don't know if it is the optimal way to do it.
CodePudding user response:
Best strategy:
Don't worry about it and just let your app handle this for you. Minified CSS and JS file delivery isn't really that slow/big and Rails will compile your assets into single files in production.
If you're determined, it is possible (your mileage may vary depending on your Rails version, and usage of Sprockets or Webpacker)
And you'll really want to understand the Rails asset pipeline (for your version of Rails) before you go nerfing these settings.
CSS inclusion/exclusion
You can ignore the asset pipeline and manually choose which CSS files to include, but you'll need to be diligent about doing this everywhere.
In your app/views/layouts/application.html
file, you have a line like this inside the <head>
tag:
<%= stylesheet_link_tag 'application', media: 'all' ... %>
This is loading application.css
, which is a compiled version of app/assets/stylesheets/application.css
and will include all CSS from all other files inside app/assets/stylesheets
Depending on your version of Rails, you'll need to turn off asset pre-compilation in either config/initializers/production.rb
or config/initializers/assets.rb
:
Rails.application.config.assets.precompile = []
Warning: this will turn off ALL asset compilation, including JS. Be sure you have a strategy to re-include JS files (based upon your asset pipeline)
You will now need to implement some logic to handle what CSS is included when. This could be in app/helpers/application_helper.rb
. It could use the view helper [controller_name
], (https://apidock.com/rails/ActionController/Metal/controller_name/class), for example, to determine which page you are on and fetch the correct CSS file.
Really rough example:
# app/helpers/application_helper.rb
module ApplicationHelper
def css_file_chooser
"/app/assets/stylesheets/#{controller_name}.css"
end
end
Then in your application.html
file, you can do something like this:
<head>
<%= stylesheet_link_tag css_file_chooser, media: 'all' ... %>
...
</head>
The catch here is you'd need to have your specific CSS files named according to your controllers. E.g. if controller_name
returns 'posts', you'd need to have a file: 'app/assets/stylesheets/posts.css'
If you do have some site-wide CSS that needs to be applied, you'd need to include a second stylesheet_link_tag
:
In this case, if you put all your global styles into app/assets/stylesheets/global.css
:
<head>
<%= stylesheet_link_tag 'global', media: 'all' ... %>
<%= stylesheet_link_tag css_file_chooser, media: 'all' ... %>
...
</head>
JS inclusion/exclusion
It's a bit dusty, but this article outlines a strategy that only loads a JS function or file if the <body>
has certain class
tags. I used to use it on my Rails 4 and 5 projects.