rake assets:precompile ignores any js & css (except application.css) #2130

Closed
snitko opened this Issue Jul 18, 2011 · 14 comments

Comments

Projects
None yet
5 participants

snitko commented Jul 18, 2011

Both on production and on development machines rake assets:precompile only compiles application.css file. I have many .scss files, they are not required into one another, but rather meant to be compiled and included in the layout independently. However, only application.css appears to be compiled. And, it does not contain all of the .scss files compiled and concatenated, it only has the contents of the application.css (which is okay and is the way I needed it, but I just thought I'd point this out).

Same thing goes for javascripts. However, because I like to keep my .coffee files under subdir named app/assets/javascripts/app they do not appear at all in public/assets. One interesting thing to mention is that I have app/assets/javascripts/lib dir where I keep libs like jQuery, in pure js. They do appear under public/assets/lib.

Image assets are doing fine.

snitko commented Jul 18, 2011

There's one more thing. I don't understand why, but when I remove nginx config lines that serve static assets (so that it becomes a Rails job) - everything works fine. The weird thing is that those assets I was talking about do not appear in public/assets, but are accessible in browser at /assets/*. It's as if config.serve_static_assets was set to true (and it's false).

snitko closed this Jul 18, 2011

snitko reopened this Jul 18, 2011

I've been testing rake assets:precompile with one app. No success. But everything worked for another app. Same version of Rails (RC4).

config.assets.precompile = %w(admin.css.erb)

So that should precompile one file. It doesn't.

Unless I'm missing something, this isn't a bug its a configuration issue. Check out the configuration guides, just add additional assets to the config

in config/application.rb (or production.rb if you want)

config.assets.precompile << "myfile.css"

You want to add the file to be "precompiled" not the actual extension. This has been working fine for me from the start. We use screen.css for our main css files, so I do it on each app.

snitko commented Jul 20, 2011

So what you're saying is that I have to manually add each new file that I want to be compiled? I'd say this is a bug.

Only the "manifest" files / the files used in layouts etc. If you have app/assets/*.js and application.js does a require_tree . etc then all you need is application.js.

How would you foresee it working any other way? Globbing assets/javascripts could lead to all sorts of issues (and defeats the purpose of manifests). It may be handy to have it automatically precompile all main/top-level manifests I guess, but I still wouldn't consider it a bug... maybe a annoying config option :).

Thinking about it I'm not sure if I'd want it making any sort of assumptions about how to precompile/merge/serve javascripts etc other than what I've listed in a manifest. I've actually thought through some scenarios where I may not want javascript precompiled at all (making whats delivered somewhat dynamic based on data/code on the back-end... now that we can mix the two somewhat). (though thats rough right now.... just posted another issue on that)

snitko commented Jul 20, 2011

No, I disagree. I understand why you're saying this, though. Your assumption is that all the pages of my webapp should have the same application.js file which is a compilation of all the files required in the source application.js.coffee. That is okay if you have a typical webapp with a heavy frontend. However, if you have, say, a social website with lots of different pages you probably wouldn't want your users to download a compiled 500kb js file just because you've changed a few lines in some source file that is only supposed to be used on a single page of the website.

I have lots of js assets that are included on different pages of the website. It becomes a pain in the ass to add them all to the config as well.

snitko commented Jul 20, 2011

Also, if you look at what SASS and Barista (coffescript rails compiler) do, I don't understand what kind of potential problems you are talking about? They simply compile each file into a specific location under public/ and that's what Rails 3.1 should really do. Would you please explain in more detail, what's wrong with this approach and why is it dangerous?

I'd say, it'd be a good idea to have some sort of wildcards like this:

config.assets.precompile << ["*.coffee"]

which would compile all the .coffee files into public/assets
Besides, in dev mode, Rails actually compiles and serves all assets as separate already.

Are you using app/assets/javascripts like public/javascripts? Assuming one huge application.js in larger-scale apps is probably bad, but one-offs don't make sense to run through the asset pipeline either in my opinion. We usually make "modules" for stuff, for instance in some apps 1 source for "frontend" (lets say application.js) and 1 source for "admin" (ie admin.js) With the pipeline we would have a structure like:

frontend.js (manifest)
-- frontend/
------ somefile.js
------ more files .....

admin.js (manifest)
--- admin/
------- files....

Then the 2 precompiled javascripts are "frontend.js" and "admin.js".

I think my confusion on your question is with the understanding of sprockets etc to begin with. To me the point is to streamline something we've been doing forever.... coding all of our js into separate files but then "packaging" them together in our deploy scripts. I've also never used coffeescript, and I'm guessing you were just making an example, but if your averaging 500k js scripts quite often that seems a little high. We utilize events for alot of stuff, calling custom jquery events vs including separate files into pages (ie a common scenario we've been using is having a particular class/module/object/plugin that responds to a custom event matching the rails controller_name:action ( event.trigger("rails:index:index") )) so having everything compiled together isn't an issue.

The issue I'm talking about with globbing/including etc probably wouldn't apply to you if you were using individual includes. In our case, most of the time our manifests aren't using require_tree etc but have the files listed in a particular order, since certain files may rely on others etc (and sprockets depends_on etc just doesn't seem to work for me). For instance alot of times we'll write a base "class" other functions rely on, if this isn't included ahead of time, things can break. With sass the same issues arise if say you include a file that describes all of your mixins after files that require them etc.

Its also worth mentioning I have absolutely nothing to do with fixing / changing any of this etc :) I was trying to give some insight how to add files to your precompile list. I've tried bug-fixing/patching before, by time I get enough free time to do it someone has finished already lol. However, I'm always interested in different approaches to the same problems/scenarios.

snitko commented Jul 20, 2011

Yep, thanks for sharing. I now understand the reasons behind the way you're handling assets. Unfortunately, I believe this doesn't apply in my case. It's like 10-15 js files in each project and I regularly add some, because I implement new features on new pages. I don't think there's a reason to be adding them to configs manually.

What I've come up with so far is creating a script which runs on the server when deploying the app. This script would generate a git ignored asset-config.rb file which would be required in production.rb and which would contain the code for adding assets. The list of assets, of course, would be generated by the script.

Anyhow, I still would like to hear what the Rails team has to say about this, because obviously they way things are implemented now is an inconvenience and I think I'm hardly the only one who's concerned about it. Honestly, one would think that REST architecture would favor the approach I'm advocating rather than the one is currently used and it's really a surprise for me why the Rails team decided not to go with it.

Give this a peek Rails Guides Asset Pipeline. Maybe that helps? I'm not sure why it would ever be an issue combining multiple js files except for file size. If "sandboxing" etc is a concern you could always wrap each file's contents in a closure and keep your global namespace happy. If they needed to communicate together, you could easily have a top-level variable/"class" that handled that for you.

I don't think REST applies here, where DRY is probably the more applicable term. Including single javascripts into misc views violates that IMO, as I see it in a similar manner as spriting in CSS. Theres situations where it would apply I'm sure, but I don't think thats the intent of the asset pipeline as a whole.

That said, config/application.rb is just ruby, and config.assets.precompile is an array of paths. Why not try globbing your files/dirs into an array and push them into the list of files to precompile if you wanted it to include them? Something like this should be close enough:

config.assets.precompile |= Dir["#{Rails.root}/app/assets/javascripts/*.*"]

That may save some time.

Just thought of something else too... you could look into making a quick template / processor for them. Just write a class that subclasses Tilt::Template. You could then name your files something like script.myext.js.coffee and exclude them from assets::precompile. Then in the MyExt class, do your compression with the uglifier gem (or whatever) and save the file in production. I'm not sure how you would tie that into your deploys offhand but that may work out as well, plus give you the benefit of being able to perform additional tasks on them / utilize them in different ways in other environments.

snitko commented Jul 20, 2011

Thanks, globbing files/dirs is a much simpler way to do what I want I haven't thought about!

josh closed this Jul 22, 2011

snitko commented Jul 23, 2011

Just a quick update. Apparently Dir glob didn't work all that well, so I just used this regexp:

config.assets.precompile = [/^[^_]/]

Which basically tells Rails to compile eveyrthing except for the _partial files (usually .scss partials).

This should be in docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment