44

I'm serving Angular 2 application with nginx using location section this way:

location / { try_files $uri $uri/ /index.html =404; } 

try_files directive tries to find the requested uri in root directory and if it fails to find one it simply returns index.html

How to disable caching of index.html file?

8 Answers 8

69

Found a solution using nginx named locations:

location = / { add_header Cache-Control no-cache; expires 0; try_files /index.html =404; } location / { gzip_static on; try_files $uri @index; } location @index { add_header Cache-Control no-cache; expires 0; try_files /index.html =404; } 
Sign up to request clarification or add additional context in comments.

5 Comments

This is the right solution The solution fro Dmitry will only work for the canonical url, if the user access from a url like /foo/, it will serve the index.html, but with no expires..
@Rem For angular it didn't work for me, basically, I have disabled global caching and it works but when I am trying same for a single file like the index.html then it not working do you have any other idea?
it works perfectly fine (except for URL ending literally with /index.html), just don't put index directive in location /
Why do we need the first block? Isn't enough just the second and third?
I think the first block should match location = /index.html or whatever index file name
24

Thanks for a great answer Rem! As He Shiming points out with the accepted solution the caching headers don't get added when visiting the root e.g. www.example.com/, but do get added when visiting any deep link, e.g. www.example.com/some/path.

After a lot of digging I believe this is because of the default behaviour of the ngnix module ngx_http_index_module, it includes index.html by default so when visiting the root /, the first location block's rules are satisfied, and index.html gets served without the cache control headers. The workaround I used was to include an index directive without specifying index.html in the first location block, forcing the root / to be served from the second location block.

I also had another problem, I included a root directive in the first location block which broke deep links and is also a bad idea. I moved the root directive to the server level.

Hope this helps, this is my solution...

server { listen 80; server_name localhost; root /usr/share/nginx/html; location / { add_header X-debug-whats-going-on 1; index do-not-use-me.html; try_files $uri @index; } location @index { add_header X-debug-whats-going-on 2; add_header Cache-Control no-cache; expires 0; try_files /index.html =404; } } 

I've included debug headers to help make it absolutely clear what location block is serving what content. It's also worth noting the unintuitive behaviour of the add_header directive, essential reading if you also intend to add headers to all requests outside of a location block.

6 Comments

props for the debug headers, showing a way to debug this as well as a solution. Teach a man to fish and all...
This solution will not cover a case where the user requests /index.html directly.
The question is around support for an Angular website where /index.html should never be directly requested. This also works well for me for a React website.
Thanks for including a mention to the confusing add_header behaviour. Saved me a headache trying to figure out why my CSP had stopped working!
why not just remove the index directive from location / entirely?
|
23

Both the try_files fallback as well as the default index directive cause an internal nginx redirect. So you can use the /index.html location to add the header for both of these two cases.

location / { try_files $uri $uri/ /index.html; } location = /index.html { expires -1; } 

index:

It should be noted that using an index file causes an internal redirect, and the request can be processed in a different location

http://nginx.org/en/docs/http/ngx_http_index_module.html

try_files:

If none of the files were found, an internal redirect to the uri specified in the last parameter is made.

http://nginx.org/en/docs/http/ngx_http_core_module.html#try_files

3 Comments

Thanks! How do you think which solution is more efficient?
This answer is better than both Rem's and Simon Ness's, since it will also cover a case where the user requests /index.html directly.
ERROR: Pre-processing of application version app-aa94-200816_122944 has failed. ERROR: Some application versions failed to process. Unable to continue deployment
9

You can use content-type mapping (should do the job for SPA with one .html file):

map $sent_http_content_type $expires { default off; text/html epoch; # means no-cache } server { expires $expires; } 

Comments

7

I got the following setup working for my Angular apps, includes changes to index.html and nginx configuration:

index.html

<meta http-equiv="cache-control" content="max-age=0" /> <meta http-equiv="cache-control" content="no-cache" /> <meta http-equiv="expires" content="0" /> <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" /> <meta http-equiv="pragma" content="no-cache" /> 

nginx.conf

location / { try_files $uri $uri/ /index.html; } location ~ \.html$ { add_header Cache-Control "private, no-cache, no-store, must-revalidate"; add_header Expires "Sat, 01 Jan 2000 00:00:00 GMT"; add_header Pragma no-cache; } 

Works both when user navigates to "site.com" and "site.com/some/url" or "site.com/#/login". The "index.html" changes are to be on the safe side mainly.

1 Comment

It stops app working when I am using the second location block I have the same configuration but don't know why it is not blessing me. Do I need any other setting?
1

Just to be safe :)

location = /index.html { add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; expires off; } 

Comments

0

I've managed to do it by adding a couple of lines in /etc/nginx/conf.d/default.conf in the nginx:stable-alpine docker:

server { listen 80; server_name localhost; #access_log /var/log/nginx/host.access.log main; location / { root /usr/share/nginx/html; index index.html index.htm; add_header Cache-Control 'no-cache, no-store, must-revalidate'; # <-- added this expires 0; # <-- added this } } 

Caching is disabled for both / and /index.html paths.

Comments

0

Found another solution.

location / { try_files $uri $uri/ /index.html; add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; add_header Expires 0; } # Cache static files location ~* \.(js|css|jpg|jpeg|gif|png|ico|svg|woff|woff2|ttf|eot)$ { expires 30d; add_header Cache-Control "public"; } 

This works fine.

The accepted solution https://stackoverflow.com/a/41632171/9272654 Doesn't work on the route refresh but this solution works fine.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.