How to serve static assets with an efficient cache policy on Nginx? - css

On mobile 📱
I'm trying to improve the page load of my site
I added
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|mp3|ogg|ogv|webm|htc|woff2|woff)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
# CSS and Javascript
location ~* \.(?:css|js)$ {
expires 1y;
access_log off;
add_header Cache-Control "public";
}
For some reasons, I feel like the changes that I just added to my Nginx is not taking any effect.
https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fwww.bunlongheng.com%2F
How should I debug this further ?

You're missing the max-age directive, from http://nginx.org/en/docs/http/ngx_http_headers_module.html
I don't think you really want CSS and JS files to expire so far out, but I could be wrong.
Also, no logging on images and all these file types? What if you're getting hotlinked or serving CSS/JS files that can't be found.
I would rethink your cache control a bit more.
# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|mp3|ogg|ogv|webm|htc|woff2|woff)$ {
expires 1M;
access_log off;
# max-age must be in seconds
add_header Cache-Control "max-age=2629746, public";
}
# CSS and Javascript
location ~* \.(?:css|js)$ {
expires 1y;
access_log off;
add_header Cache-Control "max-age=31556952, public";
}

Related

nginx: disable cache for everything except all png/svg and one js file

I'm using nginx to serve a documentation website that changes frequently. For this reason I decided to drop cache with the following:
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
proxy_no_cache 1;
proxy_cache_bypass 1;
However with this, for each page you are visiting on this site, it downloads each time an big js file (7mb) and all png/svg images, so I would like to drop cache for everything except for all png/svg and one js file that resides in the ROOT path of the project. Is possible with nginx?
Since you don't use the proxy_pass directive, tuning proxy_no_cache and proxy_bypass parameters makes no sense, you can safely remove that part from you config. For everything else the following should be enough to cache only selected files while do not cache everything else.
This should be placed to the http context:
map $uri $cacheable {
~\.(?:pn|sv)g$ 1;
/script.js 1;
}
map $cacheable $cache_control {
1 "public, max-age=31536000";
default "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
}
map $cacheable $expire {
1 1y;
default off;
}
This should be placed at the server context instead of your current configuration snippet:
add_header Cache-Control $cache_control;
expires $expire;
And take a look at this answer to not be surprised with add_header directive behavior.

Caching is not working in nginx using proxy_cache.

I'am trying to set up basic caching in my openresty nginx webserver. I have tried milion different combinations from many different tutorials, but I can't get it right. Here is my nginx.conf file
user www-data;
worker_processes 4;
pid /run/openresty.pid;
worker_rlimit_nofile 30000;
events {
worker_connections 20000;
}
http {
proxy_cache_path /tmp/nginx/cache levels=1:2 keys_zone=cache:10m max_size=100m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";
add_header X-Cache $upstream_cache_status;
include mime.types;
default_type application/octet-stream;
access_log /var/log/openresty/access.log;
error_log /var/log/openresty/error.log;
include ../sites/*;
lua_package_cpath '/usr/local/lib/lua/5.1/?.so;;';
}
And here is my server configuration
server {
# Listen on port 8080.
listen 8080;
listen [::]:8080;
# The document root.
root /var/www/cache;
# Add index.php if you are using PHP.
index index.php index.html index.htm;
# The server name, which isn't relevant in this case, because we only have one.
server_name cache.com;
# Redirect server error pages to the static page /50x.html.
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/cache;
}
location /test.html {
root /var/www/cache;
default_type text/plain;
try_files $uri /$uri;
expires 1h;
add_header Cache-Control "public";
proxy_cache cache;
proxy_cache_valid 200 301 302 60m;
}
}
Caching should work fine, there is nothing in error.log or access.log, caching system folder is empty, X-Cache header with $upstream_cache_status is not even showing, when I get headers from curl (curl -I). Now in my nginx (openresty) configuration there is no --without-ngx_http_proxy_module flag so the module is there. I have no idea what am I doing wrong please help.
You didn't define anything that can be cached: proxy_cache works togeher with proxy_pass.
The add_header defined inside the http block will be covered the one defined in the server block. Here is the snippet from the document about add_header
There could be several add_header directives. These directives are inherited from the previous level if and only if there are no add_header directives defined on the current level.
If the always parameter is specified (1.7.5), the header field will be added regardless of the response code.
So you cannot see the X-Cache header as expected.

How to solve Google Page Speed: "expiration not specified"

Analyzing an online shop (Shopware) with GooglePageSpeed results in many "expiration not specified"-Lines on every image.
I am wondering about because the webserver (nginx) adds Last-Modified-Timestamps and ETAG headers to the response of all images, resulting in an expected 304-Response on the second request.
Is ETAG/LastModified not supported by Google Page Speed?
I will provide the appropriate parts of the nginx-configuration:
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
access_log off;
add_header Cache-Control "public";
}
## All static files will be served directly.
location ~* ^.+\.(?:css|cur|js|jpe?g|gif|ico|png|html|xml)$ {
## Defining rewrite rules
rewrite files/documents/.* /engine last;
rewrite backend/media/(.*) /media/$1 last;
expires 1w;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
access_log off;
# The directive enables or disables messages in error_log about files not found on disk.
log_not_found off;
tcp_nodelay off;
## Set the OS file cache.
open_file_cache max=3000 inactive=120s;
open_file_cache_valid 45s;
open_file_cache_min_uses 2;
open_file_cache_errors off;
## Fallback to shopware
## comment in if needed
#try_files $uri #shopware;
}
Is there anythong wrong or missing?
Finally we've found out, that there was another expire-statement in the vhost-config. Reduce both to one single statement solved our issue

Leverage browser caching on nginx

I run page speed and I am getting:
"Leverage browser caching"
I have added the following directive in to my nginx.conf
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
expires 30d;
add_header Pragma public;
add_header Cache-Control "public";
}
but I am still getting the same message from google.

Nginx - How to I add Cache-Control to sitemap.xml so its never cached?

How do I set up Nginx to never cache sitemaps?
this was my idea:
location ~* \.(xml)$ {
expires -1;
log_not_found off;
}
thoughts?
Yes, thats correct if you have a add_header directive at previous levels. If not then
location ~* .(xml)$ {
add_header Expires -1;
log_not_found off;
}
A negative time sets the cache-control header to no-cache.
A better way to play with headers is to use nginx v1.4.3 that has the module more_set_headers and more_clear_headers in order to replace or set the headers from origin.
You can download the module from here.
More information HERE

Resources