SPA står for “Single Page Application”, for den består fysisk kun af een side, nemlig index.html. Dvs. alt der har med brugerfladen at gøre hentes første gang hjemmesiden besøges, og herfra foregår al kommunikation via Ajax kald til en backend.
Inde i index.html filen er der referencer til alt det andet hjemmesiden skal bruge. Disse referencer indeholder ofte det vi kalder “cache busting”. Dvs. at når man har lavet ændringer, sørger man for at filnavne i referencerne også ændrer sig. Dermed vil browseren tro at der er tale om nye filer, og hente dem påny, i stedet for at hente dem fra sit eget lager (cache).
Udfordringen opstår, når der er lavet ændringer og index.html nu refererer til nye filnavne. De gamle filer eksisterer ikke længere på serveren. Hvis index.html i det tilfælde hentes fra browserens cache, vil alle referencer pege på filer der ikke længere eksisterer.
Med en SPA er det derfor vigtigt at konfigurere både index.html og server, til at instruere browseren i IKKE at cache index.html.
I selve index.html tilføjes disse linier i <head>
sektionen:
1 2 3 |
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0"> <meta http-equiv="expires"content="0"> <meta http-equiv="pragma"content="no-cache"> |
I Apaches konfiguration tilføjes følgende:
1 2 3 4 5 6 7 8 9 |
<Directory "/sti/til/web/rodmappe"> <Files "index.html"> 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> </Directory> |
Du kan konstatere om det virker ved at hente filen med
wget
kommandoen:
1 |
wget -S http://eksempel.dk/index.html |
Før jeg ændrede apache så wget’s output således ud:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
HTTP request sent, awaiting response... HTTP/1.1 200 OK Date: Fri, 23 Aug 2019 09:31:06 GMT Server: Apache/2.4.7 (Ubuntu) Last-Modified: Thu, 22 Aug 2019 17:06:14 GMT ETag: "1353-590b7b5056d80" Accept-Ranges: bytes Content-Length: 4947 Vary: Accept-Encoding Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html Length: 4947 (4.8K) [text/html] Saving to: ‘index.html’ |
Efter genstart af Apache, ser det således ud:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
HTTP request sent, awaiting response... HTTP/1.1 200 OK Date: Fri, 23 Aug 2019 09:33:19 GMT Server: Apache/2.4.7 (Ubuntu) Last-Modified: Thu, 22 Aug 2019 17:06:14 GMT Accept-Ranges: bytes Content-Length: 4947 Vary: Accept-Encoding Cache-Control: max-age=0, no-cache, no-store, must-revalidate Pragma: no-cache Expires: Wed, 11 Jan 1984 05:00:00 GMT Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html Length: 4947 (4.8K) [text/html] Saving to: ‘index.html.1’ |
Det virker…
I mit tilfælde sidder Apache imidlertid bag Varnish HTTP Cache og Nginx som proxy. Jeg tjekker derfor også lige om de nye no-cache headers kommer hele vejen gennem Varnish og Nginx til klienten. Denne gang afvikler jeg derfor wget kommandoen på min egen computer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
HTTP request sent, awaiting response... HTTP/1.1 200 OK Server: nginx/1.14.2 Date: Fri, 23 Aug 2019 10:17:50 GMT Content-Type: text/html Content-Length: 4947 Connection: keep-alive Last-Modified: Thu, 22 Aug 2019 17:06:14 GMT Vary: Accept-Encoding X-Cache-Policy: static-file Cache-Control: max-age=3600 X-Varnish: 774695 446141 Age: 2996 Via: 1.1 varnish (Varnish/6.1) ETag: W/"1353-590b7b5056d80-gzip" X-Cache-Status: Hit/44 X-Restarts: 0 Accept-Ranges: bytes X-Restarts: 0<br> Accept-Ranges: bytes<br>Length: 4947 (4,8K) [text/html]<br> |
Desværre… det ser ud til at Varnish serverer index.html fra sin cache og ydermere mangler ‘no-cache’ som den bagvedliggende Apache ellers sender med.
I Varnish dokumentation læser jeg mig til følgende ændring:
1 2 3 4 5 6 7 |
# /etc/varnish/default.vcl sub vcl_recv { if (req.url ~ "^/index\.html" || req.url ~ "^/$") { return(pass); } } |
1 |
# systemctl reload varnish |
Efter genstart af Varnish ser headerne nu således ud:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
HTTP request sent, awaiting response... HTTP/1.1 200 OK Server: nginx/1.14.2 Date: Fri, 23 Aug 2019 10:41:38 GMT Content-Type: text/html Content-Length: 4947 Connection: keep-alive Last-Modified: Thu, 22 Aug 2019 17:06:14 GMT Accept-Ranges: bytes Vary: Accept-Encoding Pragma: no-cache Expires: Wed, 11 Jan 1984 05:00:00 GMT X-Cache-Policy: static-file Cache-Control: max-age=3600 X-Varnish: 219540 Age: 0 Via: 1.1 varnish (Varnish/6.1) X-Cache-Status: Miss X-Restarts: 0 Length: 4947 (4,8K) [text/html] |
Jeg ville også gerne have set en Cache-Control: no-cache
, men det må være Nginx der driller.