I am working on a legacy app, and I just found out that config.assets.compile was set to true in production.rb
Now, while we'll test the hell out of it on staging, I want to find all the assets which should be part of the precompile array if I can.
What I did was to go into the tmp/cache directory and have a look around:
rails#foobar-production-app:/srv/www/app/shared/tmp/cache$ find . -type f | grep foobar
./57A/651/http%3A%2F%2Fwww.foobar.com%2Fassets%2Fmathquill.css%3F
./AEE/971/http%3A%2F%2Fwww.foobar.com%2Fassets%2Fmathquill%2Fmathquill.min.js%3F
./222/C12/http%3A%2F%2Fwww.foobar.com%2Fassets%2Flegacy-b56a7fd21baf98f1ac20cd77ca77a184.js%3F
./C96/561/http%3A%2F%2Fwww.foobar.com%2Fassets%2Fmathquill%2Fmathquill.min.js%3Fv2.6%3D
And I found the file I was expecting to legacy.js which I knew was missing from precompile. Is it likely that I just need to add the files matching my domain name to the assets precompile and then it should all be OK to push to production with config.assets.compile = false or are there other places / files I should look for to fix up.
I did find a heap of assets files - like this:
./assets/D1D/0F0/sprockets%2F663a54e3907dfc958d784233a6dd0e9a
and the contents of which do contain links to images etc, but I can see those fingerprinted assets in public/assets (yes, we are actually precompiling the assets in production). Or is the presence of any of these sprockets file pointing to something that is an issue and should be fixed?
I guess my question is, how can I most easily find any missing assets, other than just setting the flag, pushing to staging, and clicking around.
Related
I have some images (svg) in my app/assets/images folder. According to the Rails Guides, all the files in the assets folder should be automatically precompiled.
However, when I reference the the image using image_tag('filename'), it shows me an Sprockets::Rails::Helper::AssetNotPrecompiled error
Asset was not declared to be precompiled in production.
It tells me to declare the file to be precompiled manually, but why should that be necessary? On top of that, why does it concern itself with the production environment when I am doing everything in development?
If you added the image after you've started the server in development, restart the server. Sprockets will then precompile that image and the error will go away.
I'm pretty sure Rails doesn't support .svg yet, hence why it would ignore it.
You'll need to include the file extensions in your config/application.rb file:
#config/application.rb
config.assets.precompile += %w(.svg)
In regards the application concerning itself with the production environment, you have to remember that the precompilation process is meant for production:
The first feature of the pipeline is to concatenate assets, which can reduce the number of requests that a browser makes to render a web page. Web browsers are limited in the number of requests that they can make in parallel, so fewer requests can mean faster loading for your application.
Concantenating assets essentially means to compile your asset files into a single file, which is typically then minified.
--
Although this can be done in real-time, it's mostly the realm of static assets (which have to be precompiled). This means that if you run the rake asstes:precompile task, it will work on the development environment, unless you call RAILS_ENV=production rake assets:precompile (which sets it to the production environment for that request.
why does it concern itself with the production environment when I am doing everything in development
The application is going to run in production, not development.
Ultimately, everything you do in development should make it easier / better to work in production. In the sense of your assets, it means that you can use many of the quirks of Rails' asset pipeline, from sprockets to preprocessors such as SASS & Coffeescript
It's probably because you didn't specify the complete image name. I ran into this problem after updating the gem too. Before I just used image_tag 'some-image', but it seems that you now have to specify what type of image/extension you want to use.
Try this: image_tag 'some-image.svg'. It worked for me.
Cheers.
I have a rails app configured on my Raspberry Pi 2. It's on my local LAN getting the same ip over and over from the router. It has mDNS configured so I can access it at mypi.local.
Configured apache2 and passenger for that local domain. Now when I enter mypi.local in my browser I see the app. Great!
It works, but for some unknown reason I get all the app's html but without any CSS and Javascript. I can interact with parts of the site which are not Javascript dependent and my browser's default CSS kicks in.
Any ideas?
If I launch WEBrick and try mypi.local:3000 everything works as expected.
this is because things work differently in development as compared to production.
few thing to note:-
No CSS or JS files will be available to your app through the asset pipeline unless they are included in other files OR listed in the config.precompile directive.Only application.css and application.js are available by default of all the CSS and JS files.
Every file that is not a Javascript file or CSS file that is in the app/assets folder will be copied by Rails into the public/assets folder when you compile your assets.So if you want to add some web fonts, you could make an app/assets/fonts/ folder and put your fonts in there, these will then be copied to public/assets/fonts folder when you compile your assets. Note that your app/assets/stylesheets/fonts.css.scss file that references those fonts will NOT be copied over unless you either added it to the config.assets.precompile directive or required it from your application.css
for config.assets.compile...If it is set to "true" (which it is by default in development) then Rails will try to find a Javascript or CSS file by first looking in the public/assets directory and if it can't find it, will hunt through your app/assets folder looking for the file. If it finds it in app/assets it will go ahead and compile on the fly and then serve this asset up.
The problem with this is that you don't notice it happening in development, then you commit everything and push to production and BOOM, everything is broken with 500 errors because production has config.assets.compile set to "false".This prevents the app from "falling back" and trying to load the file directly instead of using the asset pipeline.
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
Why don't you just have this set to "true" in every environment? Well, because it is sloooooow. And you don't want slow in production
Run RAILS_ENV=production rake assets:clean assets:precompile
check public/assets directory and verify that assets are compiled..if its not empty...that means asset pipeline is working but path is not correct.use asset_helpers to set the path of assets in css files.
I'm running a Rails 4 app on Heroku, using CloudFront as the CDN for some image assets. I have a Production app and a Staging app. On CloudFront, I have separate distributions for Production and Staging. I'm precompiling assets locally and pushing them to Heroku.
My production.rb has the following:
# production.rb
config.action_controller.asset_host = 'xxxx.cloudfront.net'
# Use special staging CDN if pushing to staging
config.action_controller.asset_host = 'yyyy.cloudfront.net' if ENV['PUSH_TO'] && ENV['PUSH_TO'].downcase == 'staging'
So I'm specifying a different asset_host depending on if I'm pushing to staging or production.
However, when I push to staging, the resulting images are missing and pointing to the Production CloudFront distribution.
I put some logging statements in the app to ensure that config.action_controller.asset_host is set to the correct Staging distribution.
If I manually access the image urls by changing the host from the Production host to the Staging host they work, so I know the fingerprints updated correctly.
My .css.scss.erb file contains:
.importance1 { background-image: image-url("<%= asset_path 'myImage1.png' %>"); }
I made sure to clear my public/assets and tmp folders.
So what could be causing my assets on Staging to be pointing to the wrong CloudFront distribution?
Update: I've discovered that only the assets that are referred to with asset_path from other assets (css files) are getting the wrong CDN host. Meanwhile, assets that are displayed from views using image_tag are working fine. This makes me think that the problem is during precompiling assets, the wrong url's are getting output from asset_path in the css files. Not sure why though. I'm calling rake RAILS_ENV=production assets:clean assets:precompile and like I've said, I tried modifying production.rb to explicitly use the staging CDN only as a test and it still didn't use it (the assets still point to the Production CDN.)
I finally figured out my problem.. Even though my staging app was using the correct asset_host, and the files were being served from the correct CDN, the urls within those files were pointing to the wrong CDN (the production CDN.) This was because while precompiling assets, the PUSH_TO env variable wasn't set, so the logic in my production.rb was using the production CDN. The solution was to do:
rake RAILS_ENV=production PUSH_TO=staging assets:clean assets:precompile
The key was the PUSH_TO=staging in there. This fixed all my problems!
It's clear that your conditional on this line is returning false:
config.action_controller.asset_host = 'yyyy.cloudfront.net' if ENV['PUSH_TO'] && ENV['PUSH_TO'].downcase == 'staging'
Either that or the asset_host won't allow being set twice. Don't know why that would be. Might be better to put that in an else block.
So fix that and you'll be set.
BUT....
Isn't this what environment files are for? Why don't you have this in your environments/staging.rb file? If it doesn't work there, you've fugged up your environment configuration and kinda defeated the whole purpose of multiple environments...
So I started investigating the asset pipeline in Rails3 and I have a desired use case that is somewhat off the beaten path... so I'm looking for a recipe.
I often run webrick locally for development and then run
Passenger+Apache for deployed instances of the app.
the app is configured with a suburi path, e.g. http:// server/approot/...
to make webrick paths work like deployed instances, I added map '/approot' do run app to config.ru. Now webrick is also at http:// local:3000/approot/...
The Confusion
Given this setup, I tried to use rake assets:precompile and have been having a lot of configuration problems between local, deployed -- missing files, incorrect paths, 404s in firebug, etc. Here's a smattering of solutions I've tried:
config.assets.initialize_on_precompile = false to application.rb to prevent trying to initialize the app for production, (we have several deployed environments and call them different names, ug.) when precompiling the assets.
config.assets.precompile += %w( *.js *.css ) to application.rb to include things like jquery.js and ujs and rails.js that were missing.
config.assets.prefix = "/approot/assets" to correct a problem where the map above (in config.ru) doesn't apply to assets, so assets had to be precompiled to ./public/approot/assets, but I'm not sure if that only works locally, i.e. if I deploy, will my asset paths be http:// server/approot/approot/(js|css|...)?
When precompiling assets, the rake task switches to env production, but then it is unclear from the Rails3 doc whether sprockets continues to compile on the fly locally and use those dynamic assets, or whether it will serve the static precompiled assets instead?
I tried putting config.serve_static_assets = true in environments/development.rb, but I'm not sure how this works with config.assets.compress = false and config.assets.debug = true. Setting the assets.debug to false just seems to hide the GET requests in the webrick log, although I saw a post saying that "solved the problem" [sic].
Requirments for a Recipe
So I'd like a recipe that does the following:
assets are consistently and correctly served from a path http://server/approot/assets/... whether run in passenger or webrick (i.e. deployed or local). If this isn't possible, then I can switch my local dev environment to use Passenger+Apache as well, it's not a big deal, but I just want to know if it's possible.
raw assets exist in /app/assets like normal Rails3, but when I precompile them, they work exactly the same way in deployed envs so that asset file references don't break (i.e. right now, there are a lot of refs looking for /assets/image/... when the path is clearly set up as /approot/assets/image.... (It's unclear from the Rails3 doc whether there are assumptions about deploying to root vs a suburi, e.g. http:// server/assets/... vs. http:// server/approot/assets/...)
sprockets can't be used in deployed environments (our restriction, sorry). So this means the rails3 app has to effectively look like a static asset app. I know this is what precompiled assets are supposed to do, but the pathing issues are preventing me from getting this working as advertised.
TL;DR - I feel like I'm trying a lot of separate things that might work if I only knew the right combination of them.
References
http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets
http://blog.55minutes.com/2012/02/untangling-the-rails-asset-pipeline-part-2-production/
http://blog.55minutes.com/2012/02/untangling-the-rails-asset-pipeline-part-3-configuration/
https://github.com/rails/rails/pull/3946
Ok, here's a potentially horrible answer, but it seems to work with webrick in two contexts now and it's the day after Halloween (although I haven't tried this approach in deployed slots yet).
Configuration
Unless otherwise mentioned, everything is defaults from a rails new app generation.
config/application.rb
config.assets.initialize_on_precompile = false
environments/production.rb (not really production, only used for rake asset:precompile)
config.assets.css_compressor = :yui
config.assets.js_compressor = :uglifier
environments/stage.rb (this is one of our deployed envs)
config.serve_static_assets = true
config.ru
This is the horrible part. I duplicated the map so that Rack would serve both the suburi and the root. So the controller action that shows the layout can have http:// server/approot/foo/index, while the assets within the layout can be loaded from http:// server/assets/...
map '/approot' do
run AppRoot::Application
end
map '/' do
run AppRoot::Application
end
Running it locally
$ rake assets:precompile
$ rails s
and in firebug I see the separate parts served by sprockets (all 200 OK):
GET /approot/
GET /assets/application.css?body=1
GET /assets/jquery.js?body=1
GET /assets/jquery.ujs.js?body=1
GET /assets/application.js?body=1
Ok, so now test a 'deployed' slot locally and see if the compiled assets work?
$ rails s -e stage
and then I see the correct precompiled assets (all 200 OK):
GET /approot/
GET /assets/application-xxxxxxxxxxxxxxx.css
GET /assets/application-xxxxxxxxxxxxxxx.js
Ok, so this isn't as nice as a real suburi solution and I think I'm going to have problems in deployed slots. Round 2, fight!
In rails 3.1, when you precompile the assets, rails create public/assets directory and add files there.
Do you version-control public/assets/*?
I use Capistrano to deploy. The last step is compiling the assets. Nothing like that gets checked into version control.
https://github.com/capistrano/capistrano/wiki/Documentation-v2.x
Checking in compiled assets, .gz files/etc, will just clutter up version control.
I was looking for an answer to this too. I found the official Rails Guide has some thoughts on this:
http://guides.rubyonrails.org/asset_pipeline.html#local-precompilation
Here's a quote of the relevant section (emphasis added):
There are several reasons why you might want to precompile your assets locally. Among them are:
You may not have write access to your production file system.
You may be deploying to more than one server, and want to avoid duplication of work.
You may be doing frequent deploys that do not include asset changes.
Local compilation allows you to commit the compiled files into source control, and deploy as normal.
There are three caveats:
You must not run the Capistrano deployment task that precompiles assets.
You must ensure any necessary compressors or minifiers are available on your development system.
You must change the following application configuration setting:
In config/environments/development.rb, place the following line:
config.assets.prefix = "/dev-assets"
The prefix change makes Sprockets use a different URL for serving assets in development mode, and pass all requests to Sprockets. The prefix is still set to /assets in the production environment. Without this change, the application would serve the precompiled assets from /assets in development, and you would not see any local changes until you compile assets again.
In practice, this will allow you to precompile locally, have those files in your working tree, and commit those files to source control when needed. Development mode will work as expected.
So, it looks like it might be a good idea to put precompiled assets into VCS on occasion.