Don't use require_tree in SASS/SCSS
Sprockets provides some directives that are placed inside of comments
called require, require_tree, and require_self.
DO NOT USE THEM IN YOUR SASS/SCSS FILES. They are very primitive and do not work well with Sass files. Instead, use Sass's native
@import directive which sass-rails has customized to integrate with
the conventions of your Rails projects.
https://github.com/rails/sass-rails
If you are not using any Sass features such as variables, functions, mixins etc you'll get by fine with require_tree. But soon as you do you will realize that they are not available in any file except in the one they are declared. Thats because each file is run in the SASS compiler before Sprockets concatenates the files together.
So you are better off using @import 'foo' and manually declaring which files and the order they should be added to the compiled stylesheet.
Its not as bad as it sounds
The default assets pipeline setup is a pretty good attempt to get lazy programmers not to shove everything into a single css/js file while still compiling it to single optimized file. It really requires require_tree . to make sense.
I usually turn off the assets generator:
# config/application.rb
module MyApp
class Application < Rails::Application
config.generators do |g|
g.assets false
# or
g.stylesheets false
end
end
end
Instead I deliberately organize the code in app/assets into modules. And any code that is not mine goes into /vendor.
You can use glob imports to import sass mixins and varibles from library folders - but it cannot/should not replace require_tree.
Using content_for instead of separate layouts
Using a seperate layout means that you have to duplicate the entire file just to change a line or two.
Instead you can use content_for to make dynamic chunks in a layout:
# application.html.haml:
!!!
%html
%head
%title My Rails app
- content_for :assets
= stylesheet_link_tag "application"
= javascript_include_tag "application"
= csrf_meta_tag
%body
= yield
Then later in the index template we can add to the head section:
- content_for :assets
= stylesheet_link_tag "some_other_file"
This would add the stylesheet link under = javascript_include_tag "application" as content_for concatenates the provided block to the content that is already captured. Use flush: true to discard any previously provided content (by the layout).
- content_for :assets, flush: true
= stylesheet_link_tag "some_other_file"