how to access assets pipeline style in production - ruby-on-rails

I have a style sheet file I put under "vendor" folder
vendor > assets > stylesheets > style.css
on my development machine if I try to access it with "/assets/style.css" I can.
In production it's not accessible. The styles on the page are broken:
ActionController::RoutingError (No route matches [GET] "/assets/style.css")
Ideas how I can make that work?
Reason why I put it in Vendor is that I only wanted those style to be include in specific pages and not be compiled and included across the site, if there is a better way to include those assets only for specific pages please advise.
BTW, I'm deploying my app on Heroku.

To access this in production you need to add that file to your precompile array in application.rb:
config.assets.precompile += ['styles.css']
You should reference the file in your view with the Rails' helpers:
stylesheet_link_tag('styles')
as this ensures the correct fingerprint is generated in the source.

I don't think the fact this stylesheet is in vendor path is a problem since sprockets should search in vendor too (from what I'm reading in the Asset Pipeline guide).
How do you try to access this CSS file? Have you tried to run
$rake assets:precompile
add/commit and re-push to Heroku remote?

Related

Rails - why is /public/assets gitignored when I need this for static imaged

In my Rails (Rails 7) app, I have some small assets (a logo and a favicon), which I want to render in production as well as in development.
I put the assets in /app/assets/images.
Since setting # config.assets.compile = true is not recommended, i run RAILS_ENV=production bundle exec rake assets:precompile. It then builds a whole lot of files (it runs esbuild app/javascript/application.tsx since I have a typescript react app running in this rails app.) and puts them in /public/assets/. But this folder is .gitignored by default. Since the folder is approx 5.5 Mb I can see why. Now, heroku docs tell me to add /public/assets/ to git and then my assets should show, but why then is this directory gitignored by default?
Am I missing something? Should I just remove the dir from my .gitignore file?
Or could I just put the assets in the public folder directly? If so, how do I add an image referencing the public folder in an erb file?
The home for static assets is the /public folder. In a default Rails 7 app you will find some error pages (e.g. /public/404.html) and icons (e.g. /public/favicon.ico) already in that folder. Files in this folder will be available both directly, example.com/favicon.ico, and under the public path, example.com/public/favicon.ico. Serving public files can be disabled, see below.
To answer your sub-question, "how do I add an image referencing the public folder in an erb file?" you need to make sure you tell Rails it's an absolute path, not a relative one somewhere in the asset pipeline. This is done with a leading forward slash.
The following compares including a logo called logo.png when it's stored in app/assets/images vs /public
<%= image_tag "logo.png" %>
<!-- becomes <img src="/assets/logo-1f04fdc3ec379029cee88d56e008774df299be776f88e7a9fe5.png"> or similar -->
<%= image_tag "/logo.png" %>
<!-- note the leading slash. This becomes <img src="/logo.png"> -->
<img src="/logo.png">
<!-- or use plain HTML if you don't need/want to use the helper -->
You can also use sub-directories; /public/images/logo.png would be available at /images/logo.png (or image_tag "/images/logo.png").
The second paragraph of chapter 2 of The Asset Pipeline Rails Guide contians more information. It mentions that this functionality depends on whether config.public_file_server.enabled is set.
In Rails 7 that config defaults to ENV["RAILS_SERVE_STATIC_FILES"].present? in config/production.rb. If you're using Heroku you can check this variable with heroku config:get RAILS_SERVE_STATIC_FILES.
The guide also has more information on how to adjust all this behaviour to have these files served by your upstream web server (e.g. nginx) or from a CDN.
Thanks for the comments, I went with adding the assets to the public folder directly and this works fine. It would be nice though if Heroku would either support a way to generate the assets after deployment by default, or describe an option to do it like I did in their docs.

RAILS 6 + Webpacker -- route error for packs/css|js/application-* in production environment

In development mode, all looks great. But when I switch over to production, bootstrap isn't found. When I look at the logs, I see errors like:
ActionController::RoutingError (No route matches [GET] "/packs/js/application-2a5806e943e281221741.js"):
This is true for both CSS and JS. When I look inside public/packs the files do exist in the corresponding subdirectory (js for the .js file, etc). So, webpacker is did it's job but puma isn't finding it. Any ideas? This is an old rails app that was migrated up several versions of rails, so I'm sure there is something I missed when tying everything together.
To expand on Tenzin's comment which I believe is the correct answer to the issue, Rails in development will always re-render assets and serve them. This is slow, but useful for seeing quick changes while developing.
When we want to deploy to production, the issue is Rails begins to serve static files which means that the server is no longer going to render them on every request. It will render them once and serve them forever. With webpacker, you can find the places these assets are served in webpacker.yml
public_root_path: public
public_output_path: packs
So if you are deploying or trying to run production locally, first be sure to compile your assets for production so these static files are created.
rake assets:precompile RAILS_ENV=production
Then make sure that wherever the server is running it has an ENV variable RAILS_SERVE_STATIC_FILES set to anything. As you can see from production.rb,
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
Is simply checking if this variable is present. If it is then it will not re-render as we discussed and it will look for the static files shown in webpacker.yml.
As another small note, if you are using something like a React UI or Bootstrap and the CSS is missing, be sure that you are importing the CSS according to the library's documentation.
For example, in Bootstrap, you will need to create an application.scss file in app/javascript/packs/stylesheets (really wherever in the /javascript folder) and import that in /javascript/packs/application.js.
In application.scss you'll want to
import "~bootstrap/scss/bootstrap"
This is of course after you have added Bootstrap to your package.json with something like
yarn add bootstrap

Do sass/scss files compile to render the final css file on production on each user page load?

I am creating a ruby on Rails app with the usual tools (rails pipeline and rails sass (gem 'sass-rails') and deploy to Heroku.
I am a newbie and what I fail to understand with scss/sass is:
when I deploy on heroku, do only .css files go the production servers or does each time a user load the homepage, herokus servers need to convert my scss files and the $ variables to serve the "final" css file to the client ?
I can cope with the larger compile time while in dev mode not in production (I'd rather avoid it). At least I need to know if even in production, the css given as example below, will need to go and fetch the scss files
Exemple:
.brand {
#include vertical-align(absolute);
color: $brandColor;
right: 1em;
}
In production the assets are precompiled, generating 2 minified files, one for the javascript and one for the css.
In development they are precompiled on each request, but you can simulate the minified one version by changing some options in your development.rb file.
Rails will use an assets pipeline in your application. Using the files application.css and application.js in your app/assets folder, it will go through the files 'required', and compile them to a single file.
It will process them from Coffee -> JS and SCSS/LESS -> CSS if these Gems are part of your hierarchy.
You can use the following to check the precompilation:
RAILS_ENV=production bin/rake assets:precompile

Rails app assets view just fine in WEBrick but no CSS, Javascript or Images from apache2?

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.

Rails 3.2 asset pipeline issue

I have a JS file defined in the app - app/assets/javascripts/client/some-client.js.coffee
In my dev env I can access this file via URL - /assets/client/some-client.js
But I cannot do the same in production? ...meaning the URL does not work, what could be wrong?
In prod, you will have access only to precompiled files, if you use the default configuration.
You can define which assets to precompile in config/environments/production.rb:
config.assets.precompile += %w( some-client.js blabla.js some-client.css ) #etc...
Run rake assets:precompile to... precompile your assets.
Learn more with this guide: http://guides.rubyonrails.org/asset_pipeline.html
If you didn't find it yet, be sure that you are accessing it through <%= javascript_include_tag "some-client" %>. As the asset pipeline handles finding where it has precompiled the asset. Along with the config.assets.precomile += %( some-client.js ). Also, if the helper function can't find that in production you might want to try moving client/ to assets/javascript/client I think it looks for assets for example javascripts files in app/assets/javascripts/ lib/assets/javascripts/ and vendor/assets/javascripts/ if I understand the asset pipeline. And it looks like you don't have it in any of those files, so it may be skipping it since it doesn't see it.
EDIT:
Looks like you have it in javascripts/ sorry. The asset pipeline should traverse subdirectories.

Resources