rails assets urls don't have digest when calling from css.scss - ruby-on-rails

I deployed my project to production and some of my assets don't work.
Those assets, which I use in html.erb with
<%= image_tag('outstaffing/outstaff2.svg') %>
work normally and return
<img src="/assets/outstaffing/outstaff2-eade8e303c63a428e7430e84866b732dae91cda0639d8d3d422c2ee86fb254aa.svg" alt="Outstaff2 eade8e303c63a428e7430e84866b732dae91cda0639d8d3d422c2ee86fb254aa">
However fonts and some images don't.
I have app/assets/fonts/RobotoCondensedRegular.ttf and app/assets/images/common/footer.svg which I try to call from css files.
style.css.scss
#font-face {
font-family: 'RobotoRegular';
src: url(font-path('RobotoCondensedRegular.ttf')) format('truetype');
}
#some_div{
background: asset-url('common/footer.svg');
}
After precompilling I have public/assets/styles-h5digest.css with
#font-face{
font-family:'RobotoRegular';
src:url("/assets/RobotoCondensedRegular-4a7c36df4318fee50a8159c3a0ebde4572abab65447ae4a651c2fe87212302b5.ttf") format("truetype")
}
This should work but returns me errors:
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
Server is trying to load assets/fonts/RobotoCondensedRegular.ttf but file name should be with digest. The same thing is with footer image.
I have already tried to change assets.rb, production.rb and application.rb in many ways. Moreover, I tried different extensions of my css files (css, css.scss, scss, css.erb) and helpers (asset-url, image-url, asset-data-url, asset_data_path, <%= asset_path() %>).
I am using Rails 4.2.0 and ruby 2.2.3.
My production.rb
config.serve_static_files = true
config.assets.js_compressor = :uglifier
config.assets.css_compressor = :sass
config.assets.compile = false
config.assets.digest = true
My application.rb
config.assets.enabled = true
config.assets.paths << Rails.root.join('app', 'assets', 'fonts')
config.assets.paths << Rails.root.join('app', 'assets', 'images', 'img', 'main')
My assets.rb
Rails.application.config.assets.precompile << /\.(?:svg|eot|woff|ttf|jpg|png)\z/
Rails.application.config.assets.precompile += ['styles.css', 'careers.css', 'team.css', 'home.css', 'services.css', 'contacts.css']
Error from log:
"GET /assets/fonts/RobotoCondensedBold.ttf HTTP/1.1" 500 1812 "http://...ip..../assets/application-6b568a81a81290ff96d145fa1f76bbf33919b85dad0f4235d8bf8759787a5076.css"
I think problem is in my server (apache) but i have no solution.

I added these two gems to my Gemfile:
gem 'rails_serve_static_assets'
gem 'rails_stdout_logging'
And set in my production.rb
config.serve_static_files = false
Now all fonts and images are working good.

Related

Rails 5.2 asset helpers not including fingerprint digests

I am in the process of upgrading our product from rails 4.1 to 5.2. I'm hung up on what appears to be an asset pipeline related issue. When I load the app in our browser, I see the following error in the server log and the app is missing all styling and javascript code that it normally has.
DEPRECATION WARNING: The asset application.js" is not present in the asset pipeline.Falling back to an asset that may be in the public folder.
This behavior is deprecated and will be removed.
To bypass the asset pipeline and preserve this behavior,
use the `skip_pipeline: true` option.
When I wget the index.html of the application, I see that all of the images and javascript urls are lacking the fingerprint digest they should have. Interestingly enough, they do have the S3 asset_host we have, so they are in fact being processed by the helpers.
To demonstrate, I have two servers which have identical configurations, but one is running 4.1 and the other 5.2. On both, I am using S3 as an asset_host and digest is turned on. I've run the following commands in their consoles:
=== Rails 4 ===
Loading qatest environment (Rails 4.1.0)
irb(main):001:0> Rails.application.config.action_controller.asset_host
=> "https://redacted.s3.amazonaws.com"
irb(main):002:0> Rails.application.config.assets.digest
=> true
irb(main):003:0> ActionController::Base.helpers.asset_path('application.js')
=> "https://redacted.s3.amazonaws.com/assets/application-042f2014ca329c79c304ab1332557040d3f7b922247202f40c28acc950f30ef8.js"
=== Rails 5 ===
Loading sean environment (Rails 5.2.1)
irb(main):001:0> Rails.application.config.action_controller.asset_host
=> "https://redacted.s3.amazonaws.com"
irb(main):002:0> Rails.application.config.assets.digest
=> true
irb(main):003:0> ActionController::Base.helpers.asset_path('application.js')
=> "https://redacted.s3.amazonaws.com/application.js
As requested, production.rb
require "#{File.dirname(__FILE__)}/includes/s3_assets"
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb
config.eager_load = true
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = false
config.log_level = ENV['SHOW_SQL'] != 'false' ? :debug : :info
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.action_mailer.raise_delivery_errors = true
config.action_mailer.perform_deliveries = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
user_name: Rubber.config.email_username,
password: Rubber.config.email_password,
address: Rubber.config.email_server,
port: Rubber.config.email_port,
enable_starttls_auto: true, # detects and uses STARTTLS
authentication: 'login' # Mandrill supports 'plain' or 'login'
}
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Raise exception on mass assignment protection for Active Record models
# config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
# config.active_record.auto_explain_threshold_in_seconds = 0.5
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fall back to assets pipelin if a precompiled asset is
# missed.
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
config.assets.enabled = true
# Nginx will serve as an asset proxy to s3, where assets are
# stored.
config.serve_static_assets = false
# instead of bundling the assets, include multiple css style includes
config.assets.debug = true
config.assets.logger = false
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# NB: The exclusion of any protocol in the asset host declaration above will allow browsers to choose the transport mechanism on the fly.
# So if your application is available under both HTTP and HTTPS the assets will be served to match.
configure_s3_assets config
config.action_controller.asset_host = "https://#{Rubber.config.s3_assets_bucket}.s3.amazonaws.com"
config.action_mailer.default_url_options = { :host => Rubber.config.external_host }
config.sequel.search_path = %w(public audit)
end
config/initializers/assets.rb
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
# Add additional assets to the asset load path
# Rails.application.config.assets.paths << Emoji.images_path
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# Rails.application.config.assets.precompile += %w( search.js )
Rails.application.config.assets.precompile += %w( *.js *.png *.eot *.woff *.ttf *.svg *.gif)
config/environments/includes/s3_assets.rb
def configure_s3_assets(config)
# Do not compress assets
config.assets.compress = false
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
# Generate digests for assets URLs
config.assets.digest = true
config.assets.enabled = true
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
config.assets.precompile += %w(
)
# find javascripts/ stylesheets/ -type f | sed 's/\.scss//' | sed 's/\.coffee//' |
# sed 's/^.*\/\///'| sort
# defaults to application.js, application.css
# application.css has home.css ?
config.assets.precompile += %w(
handlebars.js
jquery-1.7.js
json2.js
)
end
After digging around in the sprockets code, I discovered that my list of resolvers was empty. I'm not sure what was missing from my configuration, but I fixed the problem by adding the following to config/application.rb
config.assets.resolve_with = [:manifest] // in production
config.assets.resolve_with = [:manifest, :environment] // in development

font-url is resulting in asset prefix appearing twice in request for asset

In a Rails 5 application we are trying to load a custom font. In development this works as expected but in staging with asset prefix set to either /static or static it is resulting in a 404 for the font as it requests /static/static/font_name.
We are using Webpack to compile assets, we've tried removing the prefix and compiling everything to public assets but none of the items load correctly at that point. If we check the server the font has been fingerprinted and is in the static directory for the application.
SCSS file for fonts
#font-face {
font-family: 'neuzeits_book';
src: font-url('neuzeits_book.eot');
src: font-url('neuzeits_book.eot#iefix') format('embedded-opentype'),
font-url('neuzeits_book.woff2') format('woff2'),
font-url('neuzeits_book.woff') format('woff'),
font-url('neuzeits_book.svg') format('svg'),
font-url('neuzeits_book.ttf') format('truetype');
}
$font_body: 'neuzeits_book', arial;
The below is the generated css on staging.
#font-face {
font-family: 'neuzeits_book';
src: url(static/neuzeits_book-feb4879f32fd707ba88e9d1f9f2a5e901042ab66a3e01560d9b73f22ded85185.eot);
src: url(static/neuzeits_book-feb4879f32fd707ba88e9d1f9f2a5e901042ab66a3e01560d9b73f22ded85185.eot#iefix) format("embedded-opentype"),url(static/neuzeits_book-874e588d20dc28011a445eb8f645f610b6a312a7217bab344d1394187d96334a.woff2) format("woff2"),url(static/neuzeits_book-1228efc2d44dc6f54667fcba56588d3ad66c689b73e64f382370c23ebaa00975.woff) format("woff"),url(static/neuzeits_book-903eaa19a9dc9ae8210827ebf4591347271825b13bb4d25efb1fdacb1f8b9dab.svg) format("svg"),url(static/neuzeits_book-a34d20b4bf82e78b20547e4d32a4846acefc2e1f96e30ed9186a1b1594963d32.ttf) format("truetype")
}
And the below is the configuration for the assets on staging.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass
config.react.variant = :production
config.assets.compress = true
config.assets.compile = false
config.assets.digest = true
config.assets.enabled = true
config.assets.initialize_on_precompile = true
config.assets.prefix = '/static'
config.assets.paths << Rails.root.join('node_modules')
config.assets.paths << Rails.root.join('app', 'assets', 'fonts')

Rails 4 - production images and fonts not pointing to fingerprint

I imported a custom theme into my Rails app for the home page. I've copied the entire folder into app/assets/customlibrary so that I don't have to split up the theme's files.
When I run my app in the production environment, Rails isn't able to find the fingerprinted assets in app/assets/customlibrary/* when they are referenced in
app/assets/customlibrary/css/style.css.
For example in style.css, background: url("../images/hero-image.jpg") results in GET http://localhost:3000/assets/images/hero-image.jpg 404 (Not Found)
I can't figure out how to fix this. Any advice?
folder structure
app/assets/customlibary/css/*
app/assets/customlibary/css/style.css
app/assets/customlibary/js/*
app/assets/customlibary/fonts/*.(svg|eot|woff|tff|)
app/assets/customlibary/images/*
app/assets/customlibary/images/hero-image.jpg
app/assets/stylesheets/themes/theme.css'
app/assets/stylesheets/style1.css'
app/assets/stylesheets/style2.css'
application.rb
config.active_support.escape_html_entities_in_json = true
config.filter_parameters += [:password]
config.encoding = "utf-8"
# setup bower components folder for lookup
config.assets.paths << Rails.root.join('vendor', 'assets', 'bower_components')
config.assets.paths << Rails.root.join('vendor', 'assets', 'bower_components', 'bootstrap-sass-official', 'assets', 'fonts')
config.assets.paths << Rails.root.join('app', 'assets', 'customlibrary')
# customlibrary assets
config.assets.precompile += %w( css/* fonts/* images/* js/* )
# normal stuff
config.assets.precompile << /\.(?:svg|eot|woff|ttf)$/
config.assets.precompile << /\.(?:png|jpg)$/
config.assets.precompile += %w( base.css )
config.assets.precompile += ['themes/theme.css']
config.assets.precompile += ['style1.css', style2.css', ... ]
production.rb
config.cache_classes = true
config.eager_load = true
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.serve_static_assets = true
config.assets.js_compressor = :uglifier
config.assets.css_compressor = :sass
config.assets.compile = false
config.assets.digest = true
config.assets.version = '1.0'
config.log_level = :debug
Adding a path in config.assets.paths does not mean it makes the asset available from the web root of your application. (Which is my_app/public)
It adds a directory to the lookup path used by Sprockets and the asset helpers. When linking to assets from your stylesheets you can change the extension to .css.erb and use interpolation:
.class { background-image: url(<%= image_path 'image.png' %>) }
If you are using SASS, sass-rails maps the Rails asset helpers to SASS functions so you can just use:
.class { background-image: image-url("image.png") }
This does not require you to rename the file.

Rails Cloudfront assets not served

I set-up Cloudfront with Heroku for Rails and in the beginning it worked fine. I noticed in the last days that the assets are not served from cloudfront.net any longer.
Production.rb
Rails.application.configure do
config.cache_classes = true
config.eager_load = true
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.action_controller.asset_host = 'http://d2t6o5tnu5etuf.cloudfront.net'
config.serve_static_files = true
config.assets.js_compressor = :uglifier
config.assets.css_compressor = :sass
config.assets.compile = true
config.assets.digest = true
config.assets.version = '1.0'
config.log_level = :info
config.i18n.fallbacks = true
config.active_support.deprecation = :notify
config.log_formatter = ::Logger::Formatter.new
config.active_record.dump_schema_after_migration = false
end
I can reach all my assets under the cloudfront adress and in chrome i can see that application-5deb6995ce9b984d469b27c58cc92a095d19cd13e0acd622ffe426c41826e055.js gets served from cloudfront server. However all static images on the page e.g. /assets/shop/banners/2.jpg do not.
It seems to have to do with the precompiling, since it does not look for the fingerprint version of the file, or?
In my gem-file I have the following included:
group :production, :staging do
gem 'rails_12factor'
gem 'pg'
end
As tegon poined out, image_tag is or image_url is needed to serve the assets from cloudfront. I had the usual "img src" reference in my code, which will not be recognized.
Changed img src to image_tag or image_url and it was working. Thanks!
Here's an example Rails 5.2 app using CloudFront.: https://github.com/nzoschke/edgecors
In addition to the asset_host you should configure a Cache-Control header for your assets. This is so CloudFront caches the immutable application-5deb6995ce9b984d469b27c58cc92a095d19cd13e0acd622ffe426c41826e055.js named assets virtually forever.
Rails.application.configure do
config.action_controller.asset_host = "https://d372g5jsa84e2.cloudfront.net"
config.public_file_server.headers = {
'Cache-Control' => 'public, max-age=31536000'
}
end
As comments above, use the asset pipeline url helpers. Here's an example of the SCC font-url helper:
#font-face {
font-family: 'Inconsolata';
src: font-url('Inconsolata-Regular.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
body {
font-family: "Inconsolata";
}

Rails asset paths missing fingerprint in production

We've just deployed a Rails 4.0.3 app to production and have found that asset paths generated by stylesheet_link_tag and javascript_link_tag are missing their fingerprints. So instead of requesting something like application-c841bd1c82c25bb1de8452d2338479f7.js, the page is just request application.js.
RAILS_ENV=production bundle exec rake assets:precompile is successful and generates fingerprinted files.
The bits from config/environments/production.rb that seem relevant are:
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
This is running on our own Apache server, not Heroku. I've looked around quite a bit and found similar problems, but none of the troubleshooting steps for those are helping here. Thanks.
More Information
In case it is helpful, here are the full contents (commented lines removed) of our config files:
application.rb
require File.expand_path('../boot', __FILE__)
require 'rails/all'
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
module Ctrc
class Application < Rails::Application
config.ceal.application_title = "CTRC Budgeting"
config.encoding = "utf-8"
config.filter_parameters += [:password]
config.active_support.escape_html_entities_in_json = true
config.assets.enabled = true
config.assets.version = '1.0'
config.pmacs_redmine.project_identifier = 'itmat-gcrc'
config.app_data_path = '/data/web/apps/itmat/ctrc'
config.paperclip_defaults = {
path: "/data/web/apps/itmat/ctrc/:attachment/:id/:style/:basename.:extension"
}
if ENV['RAILS_RELATIVE_URL_ROOT']
config.assets.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] + '/assets'
end
end
end
production.rb
Ctrc::Application.configure do
config.cache_classes = true
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.serve_static_assets = false
config.assets.compress = true
config.assets.compile = false
config.assets.digest = true
config.i18n.fallbacks = true
config.active_support.deprecation = :notify
config.eager_load = true
end
I know that the application is running in production mode because if I set
config.assets.compile = true
in that file, the CSS and JavaScript are compiled and requested correctly.
I'm including those assets in the page like so:
<%= stylesheet_link_tag "application", media: "all" %>
<%= javascript_include_tag "application" %>
but it is still generating links to those assets like this:
<link href="/apps/itmat/ctrc/stylesheets/application.css" media="all" rel="stylesheet">
<script src="/apps/itmat/ctrc/javascripts/application.js"></script>
instead of the fingerprinted links I would expect to see.
I had a similar issue and it turned out to be a problem with the gem AssetSync. Either setting config.assets.compile = true or removing the gem resolved the issue. Compiling assets on the fly and having your Rails serve your assets might be acceptable if you're using a CDN, but generally, taking another approach is usually recommended.
For rails 4.x be sure to set the following:
config/application.rb
config.assets.enabled = true
config.assets.version = '1.0'
config/environments/production.rb
config.assets.compile = false

Resources