9

This is the similar question (with wrong title): Flutter Web - How to reload currently Active Page

Running the Flutter web app as PWA I need to allow users to initiate refresh and thus update the (web) app.

Unfortunately import 'dart:html' as html; is not allowed anymore when having the same codebase for web and mobile native apps. So following code is not the option:

  RaisedButton(
    child: Text("Update me"),
    onPressed: () {
      if (kIsWeb) html.window.location.reload();
    },
  ),

What is the correct approach?

EDIT: I have managed to use 'dart:js' in the same codebase for pwa and mobile using conditional imports. This means I can call JavaScript from within the Flutter code. Unfortunately location.reload(true); does not reload the PWA.

Ideally I would have the Flutter approach for the PWA reload / update or JavaScript workaround.

EDIT2: The whole issue is within the PWA handling of refresh button / window reload.

Unfortunately service worker's skipWaiting() can be called only from within service worker ( https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle#skip_the_waiting_phase )

The correct approach seams to be sending the skipWaiting message to the new instance of the service worker.

However skipWaiting is not yet fully supported on some browsers (iOS?) so the safer approach seams to be just unregistering the worker...

I ended up using following to stop the worker and reload.

if ('serviceWorker' in navigator) {
   navigator.serviceWorker.getRegistration().then(swr => {swr.unregister().then(
     () => {location.reload(true)}
   )});
} else {location.reload(true)}

Related:

Access service worker skipWaiting from within App build with Webpack+Workbox

https://medium.com/@nekrtemplar/self-destroying-serviceworker-73d62921d717

https://redfin.engineering/how-to-fix-the-refresh-button-when-using-service-workers-a8e27af6df68

https://deanhume.com/displaying-a-new-version-available-progressive-web-app/

Radek
  • 1,530
  • 16
  • 20
  • 1
    > Unfortunately import 'dart:html' as html; is not allowed anymore when having the same codebase for web and mobile native apps. So following code is not the option: You can still use it by adding condition to your dart "import" statement and import one or another implementation dart file: ~~~ import 'impl/impl_nonweb.dart' if (dart.library.html) 'impl/impl_web.dart'; ~~~ – Dmitri Livotov Jun 10 '21 at 13:40

3 Answers3

3

Flutter 2.10.3

In the newest version of Flutter (2.10.3 at the time of writing this), PWAs will automatically update when the serviceWorkerVersion changes in your index.html file.

From this issue, Jonah Williams comments:

"The app will update after the new version has been downloaded and the page revisited."

You can read more about general PWA support by Flutter here. For the pull request that added server worker support, see this.


If you want to allow users to manually fetch a new version of your app, you can use the universal_html package which works on all platforms.

  import 'package:universal_html/html.dart' as html;

  onTap: () {
     html.window.location.reload();
   },

Keep an eye on this issue for an improvement to how server worker caching is handled.

Code on the Rocks
  • 11,488
  • 3
  • 53
  • 61
0

A work around would be to navigate to your apps entry point route '/'

`Navigator.of(context).pushNamedAndRemoveUntil(
              '/,
              (Route<dynamic> route) => false
            );`
griffins
  • 7,079
  • 4
  • 29
  • 54
0

I maintain a set of web versions myself. When I upgrade my web application, I will upgrade the version level. Every time I start homePage, I will request the version number of the remote configuration to match the version number of the current PWA application. When the local version number is lower than the remote version number, I will refresh

  //pubspec.yaml  universal_html: ***
  import 'package:universal_html/html.dart' as html;

  getWebVersion() async{
    var res= await dio.get(web_version);
    if (locaVersion < res.version) {
       html.window.location.reload();
    }
  }