1

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.

4
  • I am deploying it using capistrano gem, but in essence it is running "standard" bundle exec rake assets:precompile Commented Sep 11, 2017 at 11:33
  • Yes, of course. Commented Sep 11, 2017 at 11:35
  • You did also make sure you restarted every Rails instance? Your NGINX config seems to have 3 but its not clear how your running them. Also look in the .sprockets-manifest-*.json file and just make sure it is referring to the right JavaScript. Commented Sep 11, 2017 at 12:12
  • Hm, the .sprockets-manifest-*.json is looking fine - it is referecing to the correct js and css version, but seems like that the server is not restarting properly. I will check it out, and get back to you (and you can create an answer after that) Commented Sep 11, 2017 at 12:38

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This is a correct answer. If others are reading, and if they use capistrano for deployment, this issue happened as I have accidentally deleted app from the roles for deployment, which consequently, didn't invoke thin:restart / thin:start correctly, which then caused server not to restart the server, which then leads to this answer. Thanks for putting the additional info as well.
0

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

2 Comments

RAILS_ENV=production rake assets:precompile ?
Thanks Guillaume, but the answer Fire Lancer gave, was the very cause of the issue, but thanks for taking time to look into it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.