Skip to content

[web] browser refresh without clearing cache? #57391

Closed

Description

@zuwuko

I can deploy my app to web server successfully, however when I update to a newer version of my app, web browser requires me to clear cache to refresh the latest app version. Is there a way around this?

Activity

  1. jonahwilliams commented on May 16, 2020

    @jonahwilliams
    Contributor

    A browser refresh is not sufficient to activate an updated service worker, as these will wait for all active clients to disconnect before deleting the old service worker. This is an intentional feature of service workers (https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle)

    In https://github.com/flutter/packages/pull/150/files , I'm adding a new API which will allow you to show "new version available" dialogs to force activate the new version.

  2. added
    platform-webWeb applications specifically
    toolAffects the "flutter" command-line tool. See also t: labels.
    on May 16, 2020
  3. cad0p commented on May 16, 2020

    @cad0p

    @jonahwilliams watching when this will get merged to main repo!

  4. jonahwilliams commented on May 16, 2020

    @jonahwilliams
    Contributor

    When its ready

  5. zuwuko commented on May 19, 2020

    @zuwuko
    Author

    @jonahwilliams Thanks. Would you please notify us here when this is implemented? I'll be watching this thread too. Thanks again for the wonderful work and the prompt response.

  6. coleweinman commented on Aug 14, 2020

    @coleweinman

    Is there a workaround for this? For me I can't ever get the new service worker to active without clearing the cache. Even when all the clients are closed, the new service worker won't activate.

  7. abdulmalekDery commented on Apr 1, 2021

    @abdulmalekDery

    Guys..anyone have found a working workaround because all these workaround doesn't work
    I've tested all of these workaround on more than host but nothing worked ..it's still show the old version until hard refresh and empty cache manually

  8. hillelcoren commented on Apr 1, 2021

    @hillelcoren
    Member
  9. treeder commented on May 20, 2021

    @treeder

    That "new version available" dialog would be very nice.

  10. artificerchris commented on Jul 22, 2021

    @artificerchris

    Just going to pile on to this, a web app that can't update itself reliably is a bad web app.

  11. akar995 commented on Nov 28, 2021

    @akar995

    still waiting for an update

  12. mhadaily commented on Nov 28, 2021

    @mhadaily
    Member

    Below is the latest script in Flutter version 2.5.0 written under index.html in web folder. as you can see that is much better compared to the previous version in order to update the service worker.

    <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 a service worker. Falling back to plain <script> tag.',
                );
                loadMainDartJs();
              }
            }, 4000);
          });
        } else {
          // Service workers not supported. Just drop the <script> tag.
          loadMainDartJs();
        }
      </script>

    if you need to have a notification or an alarm on the web to notify the user and reload the page the service worker can take control of the page. for example, what you can do is

    ....
                   if (serviceWorker.state == 'activated') {
                      console.log('Installed new service worker.');
                      loadMainDartJs();
                              // if there's an existing controller (previous Service Worker), show the prompt 
                            // you can tweak this and delay the notification once the page is load you can show a notification and ask for a new refresh
                                if (navigator.serviceWorker.controller) {
                                  // you have a better UI here, reloading is not a great user experince here.
                                  const confirmed = alert('New version of the app is available. Refresh now');
                                  if (confirmed == true) {
                                    window.location.reload();
                                  }
                            }
                    }
    
           
    ....

    You can definitely tweak the code above based on your needs.

    Tips:
    If you have not changed your index.html under the web folder and if you don't have many customizations under the web folder in Flutter, you can simply remove the web folder and run flutter create . again so the Flutter CLI will create the latest web, index.html and etc

  13. sarakisar97 commented on Nov 29, 2021

    @sarakisar97

    Any solution??

  14. yjbanov commented on Jan 27, 2022

    @yjbanov
    Contributor

    This is likely because your app uses the old service worker loading mechanism. @mhadaily posted the solution above: #57391 (comment). If that doesn't work, please open a new issue with details explaining where things break down with the new mechanism.

  15. github-actions commented on Feb 10, 2022

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  16. locked as resolved and limited conversation to collaborators on Feb 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    platform-webWeb applications specificallytoolAffects the "flutter" command-line tool. See also t: labels.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions