sassc-rails
sassc-rails copied to clipboard
Error in production mode on RoR 7.0.3.1 with Bootstrap 5.2
Ruby 3.1.2 Ruby on Rails 7.0.3.1 Third party library: Bootstrap 5.2 ( new version 5.2 released )
With bootstrap 5.1.3 (previous version) all works fine!
app/assets/config/manifest.js :
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
//= link lib/bootstrap/5.2.0/js/bootstrap.bundle.min.js
//= link lib/bootstrap/5.2.0/js/bootstrap.min.js
//= link lib/bootstrap/5.2.0/css/bootstrap.min.css
in view stylesheets and javascripts are attached via stylesheet_link_tag and javascript_include_tag
config/environments/production.rb :
config.assets.css_compressor = :sass
log/production.log :
I, [2022-08-04T22:18:02.411943 #21004] INFO -- : [65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] Started GET "/" for 127.0.0.1 at 2022-08-04 22:18:02 +0500
I, [2022-08-04T22:18:02.414687 #21004] INFO -- : [65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] Processing by ApplicationBaseController#index as HTML
I, [2022-08-04T22:18:02.422122 #21004] INFO -- : [65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] Rendered application_base/index.html.erb within layouts/application (Duration: 0.8ms | Allocations: 318)
I, [2022-08-04T22:18:10.643746 #21004] INFO -- : [65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] Rendered layout layouts/application.html.erb (Duration: 8222.5ms | Allocations: 366884)
I, [2022-08-04T22:18:10.644123 #21004] INFO -- : [65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] Completed 500 Internal Server Error in 8229ms (ActiveRecord: 0.4ms | Allocations: 368805)
F, [2022-08-04T22:18:10.645185 #21004] FATAL -- : [65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7]
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] ActionView::Template::Error (Error: Custom property values may not be empty.
on line 6:68975 of stdin
>> -size:1.25rem;--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg
------------------------------------------^
):
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7]
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] stdin:6
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sassc (2.4.0) lib/sassc/engine.rb:50:in `render'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sassc-rails (2.1.2) lib/sassc/rails/compressor.rb:29:in `call'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/sass_compressor.rb:30:in `call'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/processor_utils.rb:84:in `call_processor'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/processor_utils.rb:66:in `block in call_processors'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/processor_utils.rb:65:in `reverse_each'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/processor_utils.rb:65:in `call_processors'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/loader.rb:182:in `load_from_unloaded'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/loader.rb:59:in `block in load'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/loader.rb:337:in `fetch_asset_from_dependency_cache'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/loader.rb:43:in `load'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/cached_environment.rb:44:in `block in load'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/cached_environment.rb:44:in `fetch'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/cached_environment.rb:44:in `load'
[65dc8afa-0db3-4e0c-a7be-1b8fc43f79a7] sprockets (4.1.1) lib/sprockets/bundle.rb:32:in `block in call'
...
I'm seeing this too on a build I'm trying to deploy to Heroku. Or at least, a variation of it.
If anyone has a workaround for this, please let me know! At the moment I don't see a clear way forward.
I've spent some time today trying to narrow this down, and I hope that someone will read this testcase and might recognise the problem. The full input line from bootstrap 5.2 is .navbar{--bs-navbar-toggler-icon-bg:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280,0,0,0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");} but this can be heavily simplified as I've done below. From my testing, almost all variations work, just not for custom properties with no space after the colon and a non-empty url() function.
require 'sassc'
# An empty url() is fine
data = '.foo { --bar:url() }'
puts SassC::Engine.new(data).render
# A non-empty url() wrapped in interpolation is fine
data = '.foo { --bar:#{url("foo")} }'
puts SassC::Engine.new(data).render
# A non-empty url() with a space beforehand is fine
data = '.foo { --bar: url("foo") }'
puts SassC::Engine.new(data).render
# A non-empty url with no space works for non-custom properties
data = '.foo { bar:url("foo") }'
puts SassC::Engine.new(data).render
# A non-empty url with no space throws an error
data = '.foo { --bar:url("foo") }'
puts SassC::Engine.new(data).render
output:
.foo {
--bar:url() ; }
.foo {
--bar:url("foo") ; }
.foo {
--bar: url("foo") ; }
.foo {
bar: url("foo"); }
Traceback (most recent call last):
2: from sass-error.rb:21:in `<main>'
1: from /var/lib/gems/2.7.0/gems/sassc-2.4.0/lib/sassc/engine.rb:50:in `render'
stdin:1: Error: Custom property values may not be empty. (SassC::SyntaxError)
on line 1:13 of stdin
>> .foo { --bar:url("foo") }
------------^
If anyone recognises this, and can post a link to an issue in sassc-ruby or libsass, that would be useful! Or any workarounds gratefully received.
This worked for me: https://github.com/sass/sassc-ruby/pull/233
FYI I'm maintaining dartsass-sprockets which is a fork of this gem based on the code which @Firefishy posted. Please try it and see if it works.
@johnnyshields thanks for your work on dartsass-sprockets! I would happily switch to it, but unfortunately the bootstrap rubygem has a runtime dependency on sassc-rails, and dragging that in leads to namespace conflicts between sassc-rails and dartsass-sprockets. See also https://github.com/twbs/bootstrap-rubygem/issues/255
If anyone recognises this, and can post a link to an issue in sassc-ruby or libsass, that would be useful! Or any workarounds gratefully received.
I managed to figure out some of the root cause, along with a partial workaround. Based on my initial work, it's only a problem when the space between the : and the url( is missing, i.e. it's only when some compressed output is being re-parsed that the issue is triggered.
In our case, this is because we had a screen.css file with a sprockets-based * =require "common", and a common.scss with a sass-based @import "bootstrap" . This means that sprockets first compiles and compresses bootstrap, then pastes the output into the CSS file, then tries to compress the end result and barfs while parsing the already-compressed bootstrap.
This also explains why it worked fine for me in development, and not in testing/production, since development doesn't compress any of the SCSS files.
The true fix would be to isolate the parsing bug and patch libsass, but I'm not intending to attempt that (and libsass is deprecated anyway, so the effort might be futile). The workaround is to make sure that you a) have your main stylesheet as a .scss file, not .css and b) only use sass-based @import declarations, so that everything is parsed and compressed in one pass.
I hope this helps someone else too, it took me a while to figure out!