Cache-Control is your Friend

One of my favorite pet/personal projects is Backdrop, a simple JavaScript utility for preloading images and gracefully fading them into a webpage — as opposed to relying on the default browser behaviour of suddenly loading them into the page.

After including Backdrop within the front-end of an application served via Express on Node.js, there was a brief (but undesirable) flicker when loading images through Backdrop, but only in Safari; Firefox and Chrome behaved as desired. After digging & poking around in web inspectors and curl, I found out that Express’ (outdated) static middleware was not instructing browsers to cache the response for the image in question:

$ curl http://localhost:8081/assets/img/backdrop.jpg --head
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Fri, 19 Jan 2018 05:35:13 GMT
ETag: W/"c2fb7-1610ce9ef40"
Content-Type: image/jpeg
Content-Length: 798647
Date: Mon, 22 Jan 2018 05:59:58 GMT
Connection: keep-alive

Backdrop employs some DOM trickery behind the scenes and long story short, Safari was making a second request for the image despite it being successfully fetched from the page, and it was this second request that was the root cause of the flicker. After updating the application with serve-static and providing a max-age

const app = express(),
      serveStatic = require('serve-static');
//…
app.use(serveStatic(path.join(__dirname, 'static'), {
  maxAge: '1d'
});

… the flicker’s eliminated. You can see the fruits of my labour here.