12

I have recently implemented SSR with Cloud Functions and Firebase Hosting.

When the JS bundle is built it receives a cache bursting suffix (main.1.js).

Inside my function I have the following piece of code for caching the results of the Cloud Function

res.set('Cache-Control', 'public, max-age=300, s-maxage=300');

During deploy, I deploy hosting first and then cloud function

firebase deploy --only hosting:production && gcloud functions deploy ssr --runtime nodejs8 --trigger-http --source dist/server

The firebase hosting deployment replaces main.1.js with main.2.js.

Due to the cache bursting the file is now different (main.2.js) but because the cloud function is cached for another 5 minutes - I get errors when I visit the website (because main.1.js which is referenced in the cached version of the function, is no longer available).

How would you fix such an issue? Can I have two active deployments and activate one after another?

zo.ol
  • 283
  • 2
  • 10
  • 1
    I know this was 2 years ago, but have you managed to find a clean solution? I'm facing that exact problem right now! – tavoyne Jul 06 '21 at 11:01

1 Answers1

7

The cache control header public, max-age=300, s-maxage=300 tells any party handling a request (mainly the users's browser and Google's CDN server but can also be e.g. a proxy the user is using) how to cache the request. With your configuration both will cache the file for 5 minutes. You cannot change this behavior as there is no way to invalidate the CDN server's cache and the browser does not know about your deployment either and even if it would get a notification and reload it would get the same outdated file from the CDN.

I don't fully understand your use case but here are possible solutions:

  • Make sure not to delete old files, so you need to keep any version of main.x.js for at least the cache duration. You can use Cloud Storage to upload the file on deployment.
  • Add a fallback to the client. If main.1.js gives a 404, increment the number and try main.2.js
  • Keep the name stable, e.g. main.js
  • Add the contents of main.js to the cloud function's response body. By doing so, you ensure that the cloud functions response and the content of main.x.js get cached together and reloaded together
  • Remove the cache control header. This will lead to higher traffic on your functions and thus to higher costs.
  • Also change your function name or its rewrite on deployment to cause a cache miss
crysxd
  • 3,177
  • 20
  • 32
  • 1
    1. Using cloud storage to keep two versions alive is a good idea but we currently deploy static files to Firebase hosting and I would love to know if I can do it natively there. 2. Incrementing wouldn't work because the actual filename has hashes in it. 3. This would prevent me from doing cache bursting on the client-side cache and my users would take a very long time to get the latest file. 4. This looks very interesting. I will try it, thanks! 5. That's what we have now. I would love to leverage the cache. 6. I don't quite understand that. Can you please elaborate how this would help? – zo.ol Jun 18 '19 at 11:16
  • You need to change your system design. There is no native solution as you can't affect the caches. What about adding the script to the cloud functions response? – crysxd Jun 18 '19 at 11:18
  • Yes, as I mentioned in the comment above, that could be an interesting way to solve this. – zo.ol Jun 18 '19 at 11:22
  • Sorry, I missed that the comment was not expanded! My fault :) About 6: You can burst the cached cloud function in the same way you do it with the main.js file. If you change the name of the cloud function, it will be a cache miss. This will make maintenance much more complicated. Alternatively you an define a rewrite for the cloud function in firebase.json (you most likely already do this). Changing the rewrite name will have the same effect: cache miss after deployment – crysxd Jun 18 '19 at 11:35