HTML6 GamesFree Web Games / devlog

No install. Just play.

Free mini games right in your browser. Sign in to save your records to your account and pick up on any device.

All games
All games
All dev log posts

I deployed, and the old page kept showing for an hour

Oct 25, 2026 Β· Operations Β· ν•œκ΅­μ–΄

After deploying a new version, the old game list kept showing for about an hour. The code had been deployed correctly. The cache was the problem.

This site runs on Firebase Hosting. A browser decides how long to keep using a file without asking again from the Cache-Control header in the response. With max-age=3600 it uses its saved copy for an hour without asking the server. If a deploy changes the file in that time, the browser has no idea. So a site whose pages change needs to choose this value carefully.

In Firebase Hosting you can set response headers per address pattern under headers in firebase.json. To give HTML, JS and CSS a cache setting, I wrote this.

{ "source": "**/*.@(js|css|html|glb)",
  "headers": [{ "key": "Cache-Control", "value": "public, max-age=0, s-maxage=604800" }] }

But this site turns on cleanUrls, so it uses addresses without an extension, such as /ko/games/cloudhop. The file that actually opens is cloudhop.html, but the pattern is chosen by the address that was requested, not the file name. /ko/games/cloudhop has no .html, so it never matched the rule above.

Responses that match no rule get Firebase's default cache. The default is one hour (max-age=3600). People's browsers keep using the old page for an hour. The real trouble was that the most opened pages (the home page and the game pages) are exactly these extensionless addresses.

It was unexpected, so it took a long time to even notice. It may not sound like a big problem, but if what you just deployed only reaches users later, it can cause all sorts of trouble.

I added a rule that catches extensionless addresses separately. Every address without a dot (.) gets the same header.

{ "regex": "^[^.]*$",
  "headers": [{ "key": "Cache-Control", "value": "public, max-age=0, s-maxage=604800" }] }

This rule matches / and /ko/games/cloudhop, which have no dot, and doesn't match /portal.js or /img/logo.png, which do. I also merged the home-only rule I had before into this one.

Header rules are chosen by the requested address, not by the name of the file being sent. On a site with clean URLs, a rule written by extension can miss most of your pages. After changing headers, it is safest to check the response headers of a real page address once.

References

More posts

Add to Home Screen

  1. Tap the Share button at the bottom of the screen (top on iPad). It looks like a square with an arrow pointing up.
  2. Scroll down and tap "Add to Home Screen".
  3. Tap "Add" at the top right. The HTML6 Games icon appears on your home screen.

This works in Safari. Opened from the home screen, it runs without the address bar, like an app, and even offline.