I'm setting up a Nginx sever (version 1.17.1) for Gatsby following up the recommendation at https://www.gatsbyjs.org/docs/caching/.
The snippet below is the portion my server {} block attempting implementing the recommended caching configuration;
location ~* \.(?:html)$ {
add_header Cache-Control "public, max-age=0, must-revalidate";
}
location /static {
add_header Cache-Control "public, max-age=31536000, immutable";
}
location ~* \.(?:css|js)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
location /sw\.js {
add_header Cache-Control "public, max-age=0, must-revalidate";
}
Equally tried an if statement in place of the location {} block for defining cache configuration for the service worker file, sw.js, as below;
if ($request_uri ~ ^sw\.(?:js)$) {
set $no_cache 1;
}
Unfortunately, all files get cached successfully as expected except sw.js.
What am I doing wrong and how can I fix it so as to effectively set cache control header for sw.js to public, max-age=0, must-revalidate?
I ended up with the following nginx configuration regarding caching for Gatsby.js:
location ~* \.(?:html)$ {
add_header Cache-Control "public, max-age=0, must-revalidate";
}
location /page-data {
add_header Cache-Control "public, max-age=0, must-revalidate";
}
location = /sw.js {
add_header Cache-Control "public, max-age=0, must-revalidate";
}
location /static {
add_header Cache-Control "public, max-age=31536000, immutable";
}
location ~* \.(?:js|css)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
#OP: With which configuration did you end up? Maybe you can edit this answer to match the perfect solution after all; for people searching for "caching nginx gatsby".
The order of precedence of location is described here https://nginx.org/en/docs/http/ngx_http_core_module.html#location
When an exact match is found (using the = modifier) the search terminates and regular expressions will not be checked, so you can use that for your sw.js:
location = /sw.js {
add_header Cache-Control "public, max-age=0, must-revalidate";
}
Related
So Let's say I have my application where files are under
https://myapp.com/v1/assets/images/*.jpg
and
https://myapp.com/v1/assets/js/*.jpg
I would like to add a rule that would set no-cache headers to anything under /assets
I believe what I can for now do is
location ~ .*assets/js/.*$ {
add_header Cache-Control "public, max-age=0, no-store";
}
location ~ .*assets/images/.*$ {
add_header Cache-Control "public, max-age=0, no-store";
}
But that seems not working plus if I have many other folders under assets, I will need to add a separate rule.
Can I group everything in a pattern so that anything under /assets/* would have that header?
Thanks
This can be done via map directive:
map $uri $cache_control {
~/assets/(images|js)/ "no-cache, no-store, must-revalidate";
}
server {
...
add_header Cache-Control $cache_control;
...
}
If your URI won't match the regex, $cache_control variable would have an empty value and nginx won't add that header to its response. However there are other nginx directives that could affect Cache-Control header, i.e. expires. If you have something like expires <value>; in your config, you can use two map blocks:
map $uri $cache_control {
~/assets/(images|js)/ "no-cache, no-store, must-revalidate";
}
map $uri $expire {
~/assets/(images|js)/ off;
default <value>;
}
server {
...
expires $expire;
add_header Cache-Control $cache_control;
...
}
And take a look at this answer to not be surprised with add_header directive behavior.
Static files on my server served with browser caching via Cache-Control headers:
location ~* \.(css|js|gif|jpe?g|png)$ {
expires 1h;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
Is it possible to disable this header for certain IPs so they would not cache any files?
P.S. I need it for users who log in as administrators to see the last changes.
The expires directive can be controlled by a variable, usually generated by a map directive. See this document for details.
For example:
map $remote_addr $expires {
default 1h;
10.1.2.3 -1;
}
server {
...
location ~* \.(css|js|gif|jpe?g|png)$ {
expires $expires;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
}
It is assumed that the add_header statements can remain, even if expires is set to -1 to disable the caching.
location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico)$ {
expires 15d;
add_header Cache-Control "public, no-transform";
}
I have the code above which is supposed to cache these files for 15 days. how do I fix it so that only the files coming from /js, /css, /img will get cached instead of all?
Change the location rule to:
location ~ ^/(js|css|img)/*\.(js|css|png|jpg|jpeg|gif|svg|ico)$ {
expires 15d;
add_header Cache-Control "public, no-transform";
}
That should work
In Plesk under Additional nginx directives I've added the following cache settings.
location ~* .(jpg|js|css)$ { #shortened
etag on;
if_modified_since exact;
add_header Pragma "public";
add_header Cache-Control "max-age=31536000, public";
}
But in the wp-admin I have rewrites on the url's of these type of files.
How Do I exclude wp-admin/* and wp-includes/* from the block above?
Bit of background, I run a WordPress multisite in a subfolder. so
maildomain.com/wp-admin/stylesheet.css is actually located in
maildomain.com/wp/wp-admin/stylesheet.css
You can try to experiment with location parameter before caching directives, e.g.:
location ^~ /wp-admin/ {
}
location ~* .(jpg|js|css)$ { #shortened
etag on;
if_modified_since exact;
add_header Pragma "public";
add_header Cache-Control "max-age=31536000, public";
}
UPD. Yes, checked it on my test lab and got the 403 error. I guess empty section is not enough and some directives should be added explicitly.
Managed to add exclusion like the one below:
location ~* "^/(?!wp-admin/|wp-includes/).*\.(jpg|js|css)$" { #shortened
etag on;
if_modified_since exact;
add_header Pragma "public";
add_header Cache-Control "max-age=31536000, public";
}
I'm trying to create a conditional content_by_lua script, where the content should be set by lua only under a turthy condition.
example:
nginx.conf
location / {
content_by_lua_file /nginx/lua/nginx.lua;
root /nginx/www;
index index.html;
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff|ttf)$ {
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
}
nginx.lua
if condition then
ngx.header["Content-type"] = "text/html"
ngx.say('<H1>Hello World.</H1>');
ngx.exit(0)
else
-- serve the original content (index.html)
end
the problem is - lua scripting under nginx doesnt support 2 content directive within the same route, is there a workaround I can do?
with the current usage when the condition false I expect the index.html to be shown but receive a blank page instead
You can do a ngx.exec call which does an internal call.
nginx.conf
location / {
content_by_lua_file /nginx/lua/nginx.lua;
root /nginx/www;
index index.html;
location ~* \.(?:ico|css|js|gif|jpe?g|png|woff|ttf)$ {
expires max;
add_header Pragma public;
add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}
}
location /default_index {
root /nginx/www;
index index.html;
}
nginx.lua
if condition then
ngx.header["Content-type"] = "text/html"
ngx.say('<H1>Hello World.</H1>');
ngx.exit(0)
else
-- serve the original content (index.html)
ngx.exec("/default_index", ngx.var.args)
end