Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase Hosting Flutter Web App not clearing Cache of first deploy

We build a flutter web app and deployed it via firebase hosting. Unfortunately, we didnt configure any caching settings in our initial deploy.

Now we deployed a newer version of our website but people still get the old website shown form the first deploy. What we tried so far:

Adding version no. to our index.html:

<"script src="main.dart.js?version=1" type="application/javascript"></script>

Adding meta Data in our header in index.html:

  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
  <meta http-equiv="Pragma" content="no-cache" />
  <meta http-equiv="Expires" content="0" />

In our firebase.json we added the following headers:

"headers": [
      {
        "source": "**",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=10"
          }
        ]
      }
    ]

All of these attemps were without any luck. We think that the problem is that the newer version doesnt have those entries in the files. How can we force this to update to our newest version? We even consider opening a new firebase project if that might help.

Thanks a lot for any help!

like image 450
Gizmo Avatar asked Apr 24 '20 08:04

Gizmo


People also ask

Can I deploy flutter web project to Firebase Hosting?

So I decided to create a Flutter Web Project and deploy that to Firebase Hosting. If you want to publish it under GitHub Pages, we have also an article for that. Firebase Hosting provides fast and secure hosting for your web app, static and dynamic content, and microservices.

What is cache-control in Firebase Hosting?

This means that both the browser and the intermediate servers (meaning the CDN for Firebase Hosting) can cache the content. Note: By default, Cache-Control is set to private. This means that if you don't explicitly set Cache-Control to public, only the browser of the requesting user is allowed to cache the content.

Is it possible to deploy boiler plate counter through Firebase Hosting?

Created the boiler plate counter app and deployed through firebase hosting. It works. However, when I add url_launcher and url_launcher_web package and re-deploy, the web app shows a blank screen.

What is public public cache in Firebase?

public — Marks the cache as public. This means that both the browser and the intermediate servers (meaning the CDN for Firebase Hosting) can cache the content. Note: By default, Cache-Control is set to private.


2 Answers

Try this:

In your flutter app, in the index.html within the web folder, add a version number after the src="main.dart.js

So your new line will look like this:

<script src="main.dart.js?version=1" type="application/javascript"></script>

Then increment the version number to 2, etc before you do each build.

update june 2021: add this line in index.html as the last script in the body

like image 118
bm888 Avatar answered Oct 06 '22 17:10

bm888


I see Flutter now include this script by default in index.html if project is created recently which has serviceWorkerVersion element which updates the version when compiling:

<script>
var serviceWorkerVersion = null;
var scriptLoaded = false;
function loadMainDartJs() {
  if (scriptLoaded) {
    return;
  }
  scriptLoaded = true;
  var scriptTag = document.createElement('script');
  scriptTag.src = 'main.dart.js';
  scriptTag.type = 'application/javascript';
  document.body.append(scriptTag);
}

if ('serviceWorker' in navigator) {
  // Service workers are supported. Use them.
  window.addEventListener('load', function () {
    // Wait for registration to finish before dropping the <script> tag.
    // Otherwise, the browser will load the script multiple times,
    // potentially different versions.
    var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
    navigator.serviceWorker.register(serviceWorkerUrl)
      .then((reg) => {
        function waitForActivation(serviceWorker) {
          serviceWorker.addEventListener('statechange', () => {
            if (serviceWorker.state == 'activated') {
              console.log('Installed new service worker.');
              loadMainDartJs();
            }
          });
        }
        if (!reg.active && (reg.installing || reg.waiting)) {
          // No active web worker and we have installed or are installing
          // one for the first time. Simply wait for it to activate.
          waitForActivation(reg.installing ?? reg.waiting);
        } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
          // When the app updates the serviceWorkerVersion changes, so we
          // need to ask the service worker to update.
          console.log('New service worker available.');
          reg.update();
          waitForActivation(reg.installing);
        } else {
          // Existing service worker is still good.
          console.log('Loading app from service worker.');
          loadMainDartJs();
        }
      });

    // If service worker doesn't succeed in a reasonable amount of time,
    // fallback to plaint <script> tag.
    setTimeout(() => {
      if (!scriptLoaded) {
        console.warn(
          'Failed to load app from service worker. Falling back to plain <script> tag.',
        );
        loadMainDartJs();
      }
    }, 4000);
  });
} else {
  // Service workers not supported. Just drop the <script> tag.
  loadMainDartJs();
}
like image 30
aldobaie Avatar answered Oct 06 '22 17:10

aldobaie