ndbroadbent / turbo-sprockets-rails3

Speeds up your Rails 3 assets:precompile by only recompiling changed files, and only compiling once to generate all assets
MIT License
976 stars 78 forks source link

Issue Accessing Precompiled Asset #11

Closed iloveitaly closed 11 years ago

iloveitaly commented 11 years ago

I'm precompiling a CSS asset

# config/production.rb
config.assets.precompile += %w( store/email.css )

This asset is accessible without an issue via the web (i.e. http://domain.com/assets/store/email.css). However, when I try to access it via the command line via:

# or store/email
Rails.application.assets.find_asset('store/email.css')

I get a parse error. The CSS file is a .css.less file, and instead of pulling from the precompiled CSS file it is trying to recompile the CSS file.

Relevant stack trace:

less-2.2.1/lib/less/parser.rb:57→ block in to_css
less-2.2.1/lib/less/java_script/v8_context.rb:90→ block in do_lock
less-2.2.1/lib/less/java_script/v8_context.rb:88→ do_lock
less-2.2.1/lib/less/java_script/v8_context.rb:60→ lock
less-2.2.1/lib/less/java_script/v8_context.rb:30→ exec
less-2.2.1/lib/less/java_script.rb:26→ exec
less-2.2.1/lib/less/parser.rb:57→ to_css
tilt-1.3.3/lib/tilt/css.rb:68→ evaluate
tilt-1.3.3/lib/tilt/template.rb:76→ render
sprockets-2.1.3/lib/sprockets/context.rb:177→ block in evaluate
sprockets-2.1.3/lib/sprockets/context.rb:174→ each
sprockets-2.1.3/lib/sprockets/context.rb:174→ evaluate
turbo-sprockets-rails3-0.1.10/lib/turbo-sprockets/sprockets_overrides/processed_asset.rb:17→ initialize
turbo-sprockets-rails3-0.1.10/lib/turbo-sprockets/sprockets_overrides/base.rb:19→ new
turbo-sprockets-rails3-0.1.10/lib/turbo-sprockets/sprockets_overrides/base.rb:19→ block in build_asset
sprockets-2.1.3/lib/sprockets/base.rb:262→ circular_call_protection
turbo-sprockets-rails3-0.1.10/lib/turbo-sprockets/sprockets_overrides/base.rb:15→ build_asset
sprockets-2.1.3/lib/sprockets/index.rb:89→ block in build_asset
sprockets-2.1.3/lib/sprockets/caching.rb:19→ cache_asset
sprockets-2.1.3/lib/sprockets/index.rb:88→ build_asset
sprockets-2.1.3/lib/sprockets/base.rb:163→ find_asset
turbo-sprockets-rails3-0.1.10/lib/turbo-sprockets/sprockets_overrides/index.rb:14→ find_asset
turbo-sprockets-rails3-0.1.10/lib/turbo-sprockets/sprockets_overrides/bundled_asset.rb:12→ initialize
turbo-sprockets-rails3-0.1.10/lib/turbo-sprockets/sprockets_overrides/base.rb:23→ new
turbo-sprockets-rails3-0.1.10/lib/turbo-sprockets/sprockets_overrides/base.rb:23→ build_asset
sprockets-2.1.3/lib/sprockets/index.rb:89→ block in build_asset
sprockets-2.1.3/lib/sprockets/caching.rb:19→ cache_asset
sprockets-2.1.3/lib/sprockets/index.rb:88→ build_asset
sprockets-2.1.3/lib/sprockets/base.rb:163→ find_asset
turbo-sprockets-rails3-0.1.10/lib/turbo-sprockets/sprockets_overrides/index.rb:14→ find_asset
premailer-rails3-1.3.1/lib/premailer-rails3/css_loaders.rb:40→ load
...

Works fine without this gem installed. Any thoughts? I love the speed improvements!

sohara commented 11 years ago

+1. This is causing issues for me with the wicked_pdf gem which needs to access compiled assets. For some reason the app no longer sees the compiled asset and tries to recompile it on the server. I'm getting ActionView::Template::Error (uninitialized constant Sass::Rails::Compressor. The Sass compressor shouldn't be required for a precompiled asset.

ndbroadbent commented 11 years ago

Hey guys, I think you might be experiencing 2 different bugs here.

@iloveitaly, when you call Rails.application.assets it returns an instance of Sprockets::Environment, which doesn't actually know anything about your precompiled assets. It should be compiling every time when you call find_asset from the console, even if this gem is not loaded. So the real issue seems to be some discrepancy in the environment, maybe I've overwritten something so the less processor doesn't operate correctly. Can you tell me the error class? I can't reproduce this problem with a .css.less file in my own app, so I will have to ask you for some extra help to figure out the cause.

@sohara, your problem is more likely a compatibility issue with the wicked_pdf gem. Can you please provide an error class and backtrace? How do you produce this error? I will investigate further and see if I can reproduce the problem.

iloveitaly commented 11 years ago

Thanks for all your work on this, @ndbroadbent.

I'll reproduce the error sometime this week and get the error class any other information for you. In the meantime, from what I remember, the error was a parsing error on the less code (unable to find a variable in a file that is @imported). The error class was definitely originating explicitly from the less parser.

Here is the simplified file structure that is causing the issue:

# variables.less
@the_variable: 20px;

# email.css.less
@import "variables";

a { font-size: @the_variable; }
ndbroadbent commented 11 years ago

@iloveitaly - No problem, thanks for using the gem and helping me to iron out the bugs!

I had a very similar issue with undefined mixins in Active Admin's SASS files, but that was during the precompile task. So not sure if related, or coincidental.

I've added the following files to my Rails project:

# app/assets/stylesheets/less/variables.less
@the_variable: 20px;

# app/assets/stylesheets/less/test.css.less
@import "less/variables";

a { font-size: @the_variable; }

... and I've added 'less/test.css' to config.assets.precompile.

However, rake assets:precompile runs fine, and running Rails.application.assets.find_asset('less/test.css') from the Rails console also compiles and returns the asset without any errors.

It would be helpful to know the exact location of your variables.less file. Is it in a subfolder? It would also be really helpful if you could please post the output of the following command, run from your rails console in the production environment:

require 'pp'; pp Rails.application.config.assets; nil
ndbroadbent commented 11 years ago

@sohara - I've just had a look through the current source code of wicked_pdf, and I've noticed something that might be causing your problem.

The ability to use precompiled assets in pdfs was only added 5 months ago, but the latest gem version (0.7.9) was released over 6 months ago.

If you are using version 0.7.9, then your wicked_pdf_stylesheet_link_tag helper will be calling Rails.application.assets.find_asset, which will cause your SASS stylesheets to be recompiled every time. (See the original assets support at https://github.com/mileszs/wicked_pdf/pull/68/files).

You will need to add gem 'wicked_pdf', :github => "mileszs/wicked_pdf" to your Gemfile, in order to use the latest code with the precompiled assets support.

If you are already using the latest wicked_pdf code from the repository, then please open up a Rails console in the production environment and ensure that Rails.configuration.assets.compile equals false. If so, then there's absolutely no way that the current code should be trying to compile your SASS assets. (See WickedPdfHelper::Assets#read_asset)

Otherwise, please let me know if that solves your problem.

sohara commented 11 years ago

@ndbroadbent - Thanks so much. I was using wicked_pdf from the git repo but hadn't run bundle update for a long time, was working off a Jan 2012 commit. Should have tried updating. Thanks for looking into this. Cheers, Sean

iloveitaly commented 11 years ago

variables.less is in a subfolder: store/variables.less. email.css.less is in a subfolder as well: store/email.css.less.

assets:precompile runs fine for me as well. Just checking: did you run console as RAILS_ENV=production?

Hoping to get you some more information later today.

ndbroadbent commented 11 years ago

@iloveitaly, I've just been able to reproduce the problem by creating a fresh Rails app. I couldn't reproduce it before when I was using app that had twitter-bootstrap-rails in the Gemfile, because it was loading the less-rails gem in the production environment. If you have the less-rails gem in your :assets group, it will not be loaded by default in production. You would need to set the following environment variable for it to be loaded: RAILS_GROUPS=assets.

Please try running RAILS_ENV=production RAILS_GROUPS=assets rails console and then Rails.application.assets.find_asset('store/email.css'). That should solve your problem, but I don't know how it would work even without my gem...

I think Sprockets may have been using a cache so the asset didn't need to be recompiled, but since my gem changes the cache key, your previously cached asset needed to be recompiled.

Hope that helps!

iloveitaly commented 11 years ago

Gotcha – that is the issue, all my less related gems are in my :assets group.

Thanks for the help!

ndbroadbent commented 11 years ago

No problem, glad we could sort it out! Please let me know if you run into any more issues. I've also just fixed a bug where changes to imported files in Less (via @import) weren't being recognized, so you may want to update to version 0.1.13.

Cheers!

pistachiomatt commented 10 years ago

Hey @ndbroadbent, I have the same problem as @iloveitaly— I want to access the precompiled asset in code. If I’m reading correctly, your suggestion is to move the less gem so the server compiles the asset every time find_asset is called. Right?

Is there a way to get the file that turbo-sprockets precompiles?