I'm trying to deploy my first Rails application, but I'm getting 404 Not found for all assets (.css, .js files and images). I tried many ways of getting things work, but nothing worked. All of the asset paths look like this:
/stylesheets/application.css
My production.rb file: http://pastebin.com/SeVNEZD9
My application.html.erb, where I include these assets look like this: http://pastebin.com/gHkpfA8Z
Thanks forward for any help.
In config/environments/production.rb file add
config.assets.digest = true
Then stylesheet_link_tag will generate fingerprints url.
You need to precompile your assets for this by running this command on terminal.
RAILS_ENV=production bundle exec rake assets:precompile
After deployment you should do
RAILS_ENV=production bundle exec rake assets:precompile
Since this is your first Rails app, let me explain where your problem might be:
When you create your assets, they reside in the asset pipeline. This
is a folder located at /app/assets where your asset files will be
stored
If you want to use assets in production, there are two ways to do it -
the first is to use the assets dynamically, or to use them as static
(which is where you precompile). When you use the likes of Heroku etc,
you need to use static assets, which is why they precompile them for
you when you deploy
The problem with static assets is that Rails creates fingerprints
for them. These fingerprints basically give them a unique identifier
which you have to dynamically reference using <%= asset_path %> etc
Your problem is likely caused by you not accessing the precompiled assets correctly. The way to fix this is to use asset tag helpers like this:
#app/views/layouts/application.html.erb
<%= stylesheet_link_tag "application" %>
<%= javascriot_include_tag "application" %>
It looks like it's working now. I needed to restart the server to apply the changes. Can anybody tell me why is it that I have to restart the server to apply such changes? I want to avoid it in the future.
I'm posting my production.rb file for those who face similar problems: http://pastebin.com/7Uskvcuc
Related
Trying out rails 7, with tailwind and postcss.
I have a few stylesheets in assets/stylesheets, which I import through a file called imports.css in the same folder.
//imports.css
#import stylesheet1.css;
#import stylesheet2.css;
I then import that file in application.html.erb with the following:
//application.html.erb
<%= stylesheet_link_tag "application", "imports", "data-turbo-track": "reload" %>
On development everything works fine as intended, meshes well with tailwind. Importing works fine due to postcss. However on production (nginx, puma) it tries to pull in those files and fails. For every stylesheet I have, i see in the browser console:
GET https://mywebsite.com/assets/style/stylesheet1.css net::ERR_ABORTED 404 (Not Found)
I am trying to shift my brain over from webpacker in rails 6, not sure what I need to do here... some thoughts:
Do i need to set it up so that the stylesheets get copied over to the public/assets folder or something? Is there a setting to do that in production.rb? (I feel like rails by default should be already doing this)
Do I need to be manually precompiling these assets on deployment?
Help would be appreciated. Thanks!
#stellenberger was right and deserves the credit. In my case their solution of enabling the public file server for static assets fixed this issue for me and immediately started serving the css assets from public. I was already precompiling, they just weren't being served. I am using Rails docker containers on an EC2 in AWS behind an ALB, and there is no local NGINX so the default assumed is not correct for my scenario and needed to be changed.
The config/environments/production.rb file already provides an environment variable that will turn on the public server if present, called RAILS_SERVE_STATIC_FILES so all you need to do is set that environment variable in your build or deploy process. Since it is a presence check, any value will be truthy as the var existence is all that is checked.
Alternatively, you could also set
# config/environments/production.rb
config.public_file_server.enabled = true
in the file instead of using the ENV var, but generally the ENV vars are better than hard-coded configs.
In my case, I changed the default to
# config/environments/production.rb
config.public_file_server.enabled = ENV.fetch("RAILS_SERVE_STATIC_FILES") { true }
that way my default is true and enabled without setting the var, but I can still use the var to disable it if desired.
Do I need to be manually precompiling these assets on deployment?
Yes. Since you're not using a Node workflow now, instead relying on Sprockets and assets directly, you need the precompile step in Production.
Setting the environment variables RAILS_ENV=production and RAILS_SERVE_STATIC_FILES=true did the job for me (with Rails 7.0.4).
I tried pre-compiling my images before deployment using the command:
$ RAILS_ENV=production bin/rake assets:precompile
I am using image_tag's in my templates that work in development.
Update: config.serve_static_files is said to default to true in dev, but then is turned off in production because the assets should be provided via your web server. I currently am just using the free tier on heroku and am still running webrick, so I have this set to true, but no luck.
Update 2: When I set config.serve_static_files to false, heroku does not see any of my assets, all my stylings go away and images remain unfound. Although heroku does send a warning message upon pushing to master saying that all "config.serve_static_files does is enables serving everything in the public folder and is unrelated to the asset pipeline.". I suppose it is unrelated to the asset pipeline in that it is just serving up the assets in the public folder and does not look at our assets directory. I also see that heroku runs the precompile command upon deployment, so I don't need to do that each time.
This makes me wonder if the way I am calling my assets using the image_tag could be the problem, but I am not sure why that would be?
Update 3: The rails guide for the asset pipeline says "In regular views you can access images in the public/assets/images directory like this: <%= image_tag "rails.png" %>. I am calling for my image using this convention like so <%= image_tag("lab49", size: "80x30") %>, but the image will still not appear.
Update 4: See my answer.
If you came to this post and you are using Heroku, Heroku will accept your images only if you use the image file extension.
This will work:
<%= image_tag "lab49.png", size: "80x30" %>
This will not work (although it will locally):
<%= image_tag "lab49", size: "80x30" %>
Something to watch out for:
I had jpeg files in my assets/images folder. When I ran rake assets:precompile they were turned into .jpg files. After renaming them in my assets/images folder to .jpg, precompiling, and pushing again they displayed on Heroku just fine.
I'm implementing a site tour feature for the website https://looky.co, and I want to only send the site_tour.js file when a show_site_tour is set to true. (show_site_tour is a database column).
I have it set up in my application.html.haml (layout file). The problem is with the way heroku runs the asset pipeline.
Directory structure
\ app
\ assets
\ javascripts
\ guiders
site_tour.js
Basically the problem is that when I try to include that folder only on the condition that the database column is equal to true, heroku gives an "asset not precompiled" error.
In my application.html.haml
%head
= javascript_include_tag 'application'
- if current_user.show_site_tour == true
= javascript_include_tag 'guiders/site_tour'
So how can I make this work with the heroku pipeline?
Basically the main question is, how can I have more than one javascript file on heroku?
This answer should help.
Basically, you need to tell the asset pipeline to keep the site_tour file separate.
config.assets.precompile += %w( guiders/site_tour )
You should end up with two JavaScript files after this setting takes affect, application.js and site_tour.js.
You can test this locally by precompiling the assets using rake.
bundle exec rake assets:precompile
This will show you how the output will end up on Heroku.
It's probably also worth noting that Heroku requires that you have the following setting set to false.
config.assets.initialize_on_precompile = false
How to make Apache+Passenger and Rails Asset Pipeline work together nice?
When I deploy my locally working project, I get a 500 error
In ActionView::Template::Error occurred in pages#start: jquery-ui-1.8.21.custom.min isn't precompiled
If I grep my_project/current/assets_manifest.yml for jquery-ui-1.8, it gives me
jquery-ui-1.8.21.custom.min.js: jquery-ui-1.8.21.custom.minc50ea0bef9c2fae04ab3b50ead60fc1f.js
and this file also exists in my_project/shared/assets (along with jquery-ui-1.8.21.custom.min-c50ea0bef9c2fae04ab3b50ead60fc1f.js.gz, jquery-ui-1.8.21.custom.min.js, jquery-ui-1.8.21.custom.min.js.gz).
When I open
http://mytestserver/assets/jquery-ui-1.8.21.custom.min-c50ea0bef9c2fae04ab3b50ead60fc1f.js
in browser it gives me the correct js file.
The 500 error is raised from
app/views/layouts/application.haml:25
line 24-26 of that file are:
= javascript_include_tag "application"
= javascript_include_tag "jquery-ui-1.8.21.custom.min"
= csrf_meta_tag
So what could have gone wrong? Why is it not working?
If the file isn't being loaded by application.js then you need to add a line to application.rb so the app knows about it:
config.assets.precompile += ['jquery-ui-1.8.21.custom.min.js']
shared/assets is not a place that the asset pipeline typically looks for files.
Typically the asset pipeline looks in app/assets, it may look in lib/assets and I'm pretty sure it looks in vendor/assets also. But it's possible that the vendor/assets is not included by default, which I talk about below.
Per Rails convention I suggest you put that dependency in vendor/assets/javascripts
If you want to add search directories to the asset pipeline it's just a simple modification to config.application.rb
in the YourProject::Application declaration, add:
config.assets.paths << Rails.root.join("vendor/assets/javascripts")
Or whatever other path you want.
I think I solved it.. I think this were the steps:
renaming the rake-namespace of capistrano deployment (possible duplication of namespace and var damage) which was also doing the precompilation
add each js file that I include via javascript_include_tag to config.assets.precompile for production environment like #Simon suggested
in config.assets.precompile they seem to be mentioned without .js-extension, whereas in the javascript_include_tag directives they should be included with .js-extension
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.