Reputation: 5380
I have a server where I have set nginx and Rails app. When I load page, my css and javascript links goes like this:
<link rel="stylesheet" media="all" href="/assets/application-01b482b5cbd306773ee4d7bc86b222a5d0c9b1c2dc82302957bc752dc079f6aa.css" data-turbolinks-track="true" />
<script src="/assets/application-cc1e40cfd63b56dd14a482241c0d44cc69c37206eeeb546d3f88ce94e09f8abc.js" data-turbolinks-track="true"></script>
The problem is when I load the page, I am always getting an error 404 Not Found
for the javascript file /assets/application-cc1e40cfd63b56dd14a482241c0d44cc69c37206eeeb546d3f88ce94e09f8abc.js
BUT curiously, not for css file.
Also, every time I change some of the javascript in the Rails and deploy the application (and therefore the javascrpt gets compiled,but the javascript fingerprint stays always the same!, where it should probably be changed).
My production.rb
file looks like this:
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.serve_static_assets = false
config.serve_static_files = false
config.assets.js_compressor = :uglifier
config.assets.compile = true
config.assets.digest = true
config.assets.version = '1.0'
config.assets.precompile = ['*.js', '*.css', '*.css.erb']
end
And my nginx configuration file looks like this:
upstream rails {
server localhost:3000;
server 127.0.0.1:3000;
server 127.0.0.1:3001;
server 127.0.0.1:3002;
}
server {
listen 80;
server_name my_site.com www.my_site.com;
root /home/httpd/projects/my_site/current/public;
index index.html;
location ~* ^/assets/ {
add_header Last-Modified "";
add_header ETag "";
gzip_static off;
expires max;
add_header Cache-Control public;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
try_files /system/maintenance.html $uri $uri/index.html $uri.html @ruby;
}
location @ruby {
proxy_pass http://rails;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
}
}
And my /public/assets/
folder contains:
application-d211d1f163557c0f66d9380e7d485b799459ef763d25d832edc6c238dc502ac1.css
application-dd50fcd16cb3e12c063da05aa994afc5fe1558715e1af955cee8a633f5597171.js
(Where both version doesn't match the version in the generated html file, noted at the beginning of the question.)
I have tried clearing tmp
folder, but it didn't help. Also, there doesn't seem to be nginx cache
folder, so I haven't deleted it.
I am using capistrano for deployment.
What am I missing?
Edit (additional info for those who encounter the issue):
If you use capistrano for deployment, make sure you have app
set for the roles
for deployment, which if they if it isn't added to the roles, it will not invoke all required steps when running thin:restart
/ thin:start
. In fact, it will run all the predefined commands, except the one which starts/restarts the server.
Also, if you are starting a server in production (in my case thin
) and you receive a LoadError: incompatible library version
then try to find a running server with lsof -wni tcp:3000
and kill the server. Then start the deployment again and it should work now.
Upvotes: 1
Views: 827
Reputation: 1537
You should use the Gem uglifier
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
Then bundle install
Then rails assets:precompile
Upvotes: 0
Reputation: 30145
Rails in production mode uses a manifest file .sprockets-manifest-<checksum>.json
(located by config.assets.prefix
, public/assets/
is the default). This file along with the assets is generated by rails assets:precompile
for Rails 5. Older versions have the same concept, but use rake
and the filename may be slightly different.
The manifest is loaded by Rails when it starts in production mode and is used to determine the URLs to use for assets, such as with javascript_include_tag
or image_path
, Rails does not use or monitor the files in app/assets/
in production.
If you are having trouble with assets in production, make sure this manifest is present and refers to correct files (its a simple structure to read manually).
If it does, then make sure all Rails processes got restarted after the manifest was created/uploaded, because old processes will be using outdated assets. rails restart
should do this, but depends on how you are running your processes.
Also its generally a good idea to leave all old asset files "online" for a short while when updating a live site as users that already loaded a page will have URLs for the old assets, but may not have actually downloaded them yet (in addition to if they were literally opening the page at that moment, things like images in collapsible sections, or CSS backgrounds for undisplayed classes may not have been initially downloaded).
Take even more care if hosting assets centrally on a static file store with multiple separate Rails servers, as while your restarting them some will be referring to old assets and some new.
Upvotes: 2