Firebase hosting: How to prevent caching for the index.html of an SPA

zevdg picture zevdg · Feb 2, 2018 · Viewed 11.6k times · Source

I'm hosting an SPA on firebase where almost all paths get rewritten to index.html. I'm using webpack hash based cache busting, so I want to always prevent caching of my index.html but not any other files. I'm finding it surprisingly difficult to do so. Specifically, my file layout looks like this

/
├── index.html
├── login.html
├── js
│   ├── login.ba22ef2579d744b26c65.bundle.js
│   └── main.6d0ef60e45ae7a11063c.bundle.js
└── public
    └── favicon-16x16.ico

I started naively with "sources": "index.html" before reading this quote from the docs.

Each definition must have a source key that is matched against the original request path regardless of any rewrite rules using glob notation.

Ok, so instead of a simple glob that specifies the files I want these headers on, I guess I need one on paths. Since most paths redirect to index.html, I need a glob that excludes all the paths I do not want to put these headers on.

For reference, my firebase.json hosting section looks like this:

{
  "hosting": {
    "public": "dist",
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "cleanUrls": true,
    "trailingSlash": false,
    "headers": [
      {
        "source": <<<WHAT-GOES-HERE?>>>,
        "headers": [
          {
            "key": "Cache-Control",
            "value": "no-cache, no-store, must-revalidate"
          },
          {
            "key": "Pragma",
            "value": "no-cache"
          },
          {
            "key": "Expires",
            "value": "0"
          }
        ]
      }
    ]
  }
}

So, to give some examples that redirect to index.html and should not be cached

mysite.com  
mysite.com/  
mysite.com/foo/bar/baz  
mysite.com/index.html 

Note: I could live if that last one got cached since it doesn't get used in practice.

And the things that do not redirect to index.html and should not be cached

**/*.* (ideally excluding index.html)
mysite.com/login  

The closest I've gotten on my own is **/!(login|*.*) which works for almost everything listed above, but inexplicably does not work on mysite.com or mysite.com/. Those 2 pages are not getting matched by this glob and I cannot figure out why.

Answer

Gijo Varghese picture Gijo Varghese · Feb 12, 2018

Here is the config that I'm using. The logic is to use cache for all static files like images, css, js etc.. For all others, i.e "source": "/**" set cache as no-cache. So for all other files, that maybe example.com, example.com/index.html, example.com/about-us, example.com/about-us.html cache will not be applied.

{
  "hosting": {
    "public": "dist",
    "headers": [
      {
        "source": "/**",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "no-cache, no-store, must-revalidate"
          }
        ]
      },
      {
        "source":
          "**/*.@(jpg|jpeg|gif|png|svg|webp|js|css|eot|otf|ttf|ttc|woff|woff2|font.css)",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=604800"
          }
        ]
      }
    ],
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"]
  }
}