rails serving static asset path which doesn't match precompiled manifest - ruby-on-rails-3

I've tried reading through many other questions on how to properly configure nginx to serve static assets for rails 3.2 but no matter what I attempt the asset path being loaded by my browser does not match the asset version specified in manifest.yml after precompile and as a result all my assets are not found.
My nginx config is as follows:
location ~ ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
expires 1y;
add_header Cache-Control public;
gzip_static on;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
I've also checked the root path in nginx is correct. I'm using nginx with unicorn via a Unix Domain Socket.
First time I set this up everything loaded fine. Then I modified an asset and re-deployed. That asset was then broken. I then bumped the asset version and now all assets are broken. I've tried clearing my local cache in case that was causing problems but it didn't help.
I'm starting to tear my hair out at this point, any help would be greatly appreciated.

After more investigation I found the unicorn process wasn't properly restarting when updating.

Related

Remove a header based on query param with varnish

I want to remove a cache-control header from URL's with a specific query params. e.g. when the query paramater ajax=1 is present.
e.g
www.domain.com?p=3&scroll=1&ajax=1&scroll=1
These are getting cached by chrome browsers for longer than I would like and I would like to stop that in this specific case. I have tried with .htaccess which works for static files however not in action on the URL's mentioned above.
RewriteEngine on
RewriteCond %{QUERY_STRING} (^|&)ajax=1(&|$)
Header unset "Cache-Control"
I could use a cache buster in the next website release but difficult in production and worried it would unnecessarily cache lots of files in user browsers so would rather achieve server side.
My server has Cloudflare then NGINX terminating SSL to Varnish then Apache with a Magento 2 instance running on there. So thinking i could possibly achieve this with NGINX or Varnish configs, or even Cloudflare. I however couldn't seem to find a way to achieve this with page rules in Cloudflare, or could not find examples for Varnish or Nginx.
I'm assuming you don't want to cache when ajax=1 is part of your URL params?
You can do this in Varnish using the following VCL snippet:
sub vcl_backend_response {
if(bereq.url ~ "\?([^&]*&)*ajax=1(&[^&]*)*$") {
set beresp.http.cache-control = "private, no-cache, no-store";
set beresp.uncacheable = true;
}
}
This snippet will make sure Varnish doesn't cache responses where the URL contains an ajax=1 URL parameter. It will also make sure any caching proxy that sits in front will not cache, because of the Cache-Control: private, no-cache, no-store.
Is this what you're looking for?

apache2 DirectoryIndex change does not bypass cached index

I am trying to make sure that visitors to my website see the latest version. To this end I have written a script to rename appropriate files and requests so that they append a fresh version number at build time. This includes the index file, let's call it index-v123.html.
I have uploaded this built source and pointed my apache2 server to the new index file by including
DirectoryIndex index-v123.html
in my apache2.conf. I have restarted it, and when viewing the website in chrome incognito mode or on hard refresh I can see that all the new files are loaded and the website works as expected.
My issue is that in my normal browser, when I visit the URL, I still load up a cached version of index.html. Clearly changing the DirectoryIndex didn't convince the client to go to the new index file like I'd hoped...
So can I do anything to make this happen?
(Also may be relevant: I am running a progressive web app using Polymer 2.0, with a service-worker.js that is built automatically by polymer build.)
This turned out to be a service worker issue: service-worker.js was being cached on the client side, and hence was providing outdated content as if the client was in offline mode. Could only be updated by deregistering the worker. The solution was to implement max-age=0 on the service worker at the apache2 server side:
<Files index.html|service-worker.js>
FileETag None
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</Files>
Was surprised this wasn't better highlighted in the polymer build/production docs somewhere. For reference, in the google primer on service workers it says:
The caching headers on the service worker script are respected (up to
24 hours) when fetching updates. We're going to make this opt-in
behaviour, as it catches people out. You probably want a max-age of 0
on your service worker script.

Clear web browser cache programmatically

I am working on a website with PHP in backend and AngularJS in frontend. and it's served via apache2.4.
My problem is when I update my website to a new version some users cannot see the latest modifications, so I added this .htaccess to force cleaning the cache every 1 hour, but it doesn't work as I expected.
FileETag None
<ifModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=3600, must-revalidate, private"
</ifModule>
Could you give me the right cache configuration to force the browsers to get the last update whenever a new version is available?
Within your build process, you could append a query parameter to your static files such as JS / CSS like : app.js?1476109496 (where epoch is a unique reference such as deployment epoch, commit hash or similar) which would cause browsers to request a new version without needing to mess with your .htaccess.

Nginx not serving precompiled assets in subdirectory

I have a RoR3 server deployed in Amazon EC-2.
My assets are precompiled. I ran rake:assets:precompile as a part of my capistrano deployment task.
For example:
assets/home/separator.png is precompiled in public/assets/home/separator-7abf67950e9a27f371d2b5638de4320b.png
I cant see the separator.png in the file
public/assets/home/manifest.yml, why?
This is my nginx configuration for the assets:
location ~* ^/(assets)/ {
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
The Rails app is searching for assets/home/separator-f4571b5883207774be6edc5745de4755.png, which doesnt exists.
Any ideas?

How to serve cached ruby apps from nginx rather than unicorn?

I have a rails 3.0 app, and it has a good amount of traffic, the app it's running through the combination of Nginx and Unicorn. The thing is that unicorn and it's workers consume a lot of resources, and because of the nature of my app, a lot of records are pulled from the database, then it's like serving almost static files generated with those database records
I was wondering if you can generate this kind of static files, cache them, serve them through nginx instead of the app through unicorn to use less resources and kind of reloading the cache after 1000 request
I'm beginning my research about that, I don't know a lot of server configuration, so I hope you guys have any advise for me, it would be great!
thanks!
I assume you mean How do I serve my static assets from nginx rather than Unicorn
I just solved this problem and here is a snippet of my nginx.conf
# Prefer to serve static files directly from nginx to avoid unnecessary
# data copies from the application server.
try_files $uri/index.html $uri.html $uri #app;
# Set Far Future Cache on Static Assets
# All requests starting with /xyz/ where xyz is
# one of the options below (~* == case insensitive)
location ~* ^/(images|javascripts|stylesheets)/ {
# Per RFC2616 - 1 year maximum expiry
# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
location #app { ... }
I am using Rails 3.0.10 so you my need something like ^/assets/ instead. The ~* directive tells nginx to do a case in-sensitive reg-ex compare. Also you don't need to escape the backslashes as you would in other languages.
Here is the Nginx documentation on that: http://wiki.nginx.org/HttpCoreModule#location