facebook / create-react-app

Set up a modern web app by running one command.
https://create-react-app.dev
MIT License
102.51k stars 26.77k forks source link

Service Worker weird caching #5316

Open gabrielmicko opened 5 years ago

gabrielmicko commented 5 years ago

Is this a bug report?

Yes

Did you try recovering your dependencies?

Yes

Which terms did you search for in User Guide?

https://github.com/facebook/create-react-app/issues/2398

Environment

Environment Info:

System: OS: macOS High Sierra 10.13.6 CPU: x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz Binaries: Node: 9.10.0 - /usr/local/bin/node Yarn: 1.10.1 - /usr/local/bin/yarn npm: 5.6.0 - /usr/local/bin/npm Browsers: Chrome: 69.0.3497.100 Firefox: 62.0.3 Safari: 12.0 npmPackages: react: ^16.5.2 => 16.5.2 react-dom: ^16.5.2 => 16.5.2 react-scripts: 2.0.4 => 2.0.4 npmGlobalPackages: create-react-app: 2.0.3

Steps to Reproduce

(Write your steps here:)

  1. Clone https://github.com/gabrielmicko/react-create-app-pwa. It is almost a clean app of react-create-app.
  2. Install dependencies. yarn install. Create a build. yarn run build.
  3. Run serve -s build (if you don't have serve yarn global add serve), or node server.js.
  4. Open localhost:5000. You should see service worker precaching files.
  5. Do some change in the App.js and run yarn run build again.
  6. Refresh the page and check your console. You should see the new files. It will log an "Update happened" message.
  7. Refresh the page to see the updates.
  8. Can't see the changes I made.

Expected Behavior

After refreshing the page at point 7. I should see my changes.

Actual Behavior

I see the old version of my app.

(Write what happened. Please add screenshots!)

Reproducible Demo

https://www.youtube.com/watch?v=Hl5HbZ0TWoY

Timer commented 5 years ago

You need to close all tabs or fully close the browser to see the changes reflected. A page reload will not reflect the changes.

FezVrasta commented 5 years ago

Hey @timer, from what I see on the video, OP is using the incognito mode with a single open tab.

I cloned the repo and I can reproduce the problem as well. Maybe something is wrong with the V2 service worker?

Timer commented 5 years ago

/cc @jeffposnick

gabrielmicko commented 5 years ago

Is this the expected behaviour? Does it happen only on localhost? When onUpdate gets called I would like to add a popup which prompts the user to reload the page.

Timer commented 5 years ago

Yes -- the expected behavior is that you must close all tabs or browser before the new content appears. This is the behavior everywhere, not just on localhost.

You should be able to override this via ServiceWorkerGlobalScope.skipWaiting() but you need to make sure you coordinate this across all instances of your apps running in their browser.

FezVrasta commented 5 years ago

May we convert this into a "doc improvement" issue so that we keep track of this? I think the current documentation should at least mention it.

Timer commented 5 years ago

Yeah we should probably note this in https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#offline-first-considerations

gabrielmicko commented 5 years ago

In the meantime I found this: https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin skipWaiting: true does the job.

jeffposnick commented 5 years ago

Yes, this does warrant improvements to the v2 docs. I can tackle that next week.

FYI, https://github.com/facebook/create-react-app/issues/3613#issuecomment-353467430 is the best explanation of why defaulting skipWaiting to false was the safest thing to do for c-r-a v2.

tl;dr is that if skipWaiting is true and you lazy-load resources, there's a decent chance that you might end up trying to lazy-load a URL that no longer exists in the service worker's cache or on the server. If you don't lazy-load versioned URLs and you want the old behavior, then changing your config to using skipWaiting: true is the alternative.

mymattcarroll commented 5 years ago

@gabrielmicko , @jeffposnick , Can the skipWaiting: true option be applied without ejecting?

mymattcarroll commented 5 years ago

On this line the workbox-webpack-plugin is registered with clientsClaim: true and the documentation for workbox-webpack-plugin's skipWaiting option says

Whether or not the service worker should skip over the waiting lifecycle stage. Normally this is used with clientsClaim: true.

Should the default behaviour be setting clientsClaim: true and skipWaiting: true?

gabrielmicko commented 5 years ago

@mymattcarroll yes, that way you get the update asap. For now I don't know how am I going to get a callback about the update onUpdate seems to be broken if skipWaiting is set to true. I'll take a look later. Also I don't know how I can add skipWaiting: true without hacking in the node_modules. Any idea?

gabrielmicko commented 5 years ago

Finally I was able to test with "react-scripts": "^1.1.0". Actually it works how it should!

serviceWorker.register({
   onUpdate:() => {
       //Some UI notification comes here, then reload
       window.location.reload();
    }
})

Once it reloads, I instantly see the change, whereas in create-react-app v2 I won't. I guess this is something that has to be addressed. Please at least make it configurable. For example:

serviceWorker.register({
    skipWaiting: true
    onUpdate:() => {
});

This case onUpdate would instantly fire once skipWaiting() get's called.

What do you think?

/cc @jeffposnick

Edit: actually I am a little confused if it could be added to serviceWorker.js file. Cause I guess it has to be in the service-worker.js.

mymattcarroll commented 5 years ago

@gabrielmicko, it will have to be a build time configuration as it needs to be added to the webpack configuration here.

Perhaps configuration in package.json? The package.json is already being used for build time configuration using the browserlist property. Maybe something like:

{
  "serviceWorkerOptions": {
    "skipWaiting": true
  }
}
gabrielmicko commented 5 years ago

@mymattcarroll This would be awesome. Other questions is how do you let serviceWorker.js know that skipWaiting has been called? The developer want's to subscribe to that event, so he can let the users know there was an update.

mymattcarroll commented 5 years ago

@Timer, it seems the default behaviour of the service worker has changed between v1 and v2. Our project is no longer hitting this line to allow us to prompt the user when new content is available by just refreshing the current page.

Was this intentional?

If it was, I have been able to make changes to a local fork to get v1 behaviour to occur again by making the following changes:

  1. Updating the serviceWorker.js check the event object passed to registration.installing.onstatechange instead of checking registration.installing.state (it seemed there was a race condition where multiple state changes were occurring so fast that registration.installing.state was always equal to 'activated')
  2. Updating webpack.config.prod.js to pass skipWaiting: true to workbox-webpack-plugin configuration

I would be happy to contribute with a pull request if you believe these changes are desirable for others.

If setting skipWaiting: true by default is not desirable, would you consider a configuration option, perhaps in package.json? I would be happy to work on making the UX similar to how the browserslist property is added to package.json with a prompt.

This library is awesome, would hate to consider ejecting...

gabrielmicko commented 5 years ago

Very well said @mymattcarroll! This is what I realised as well! I guess the default behaviour should match v1 so that devs would not need to change anything!

jeffposnick commented 5 years ago

So I had mistakenly thought that being able to override the default Workbox options via an external config file had made it into c-r-a v2 branch, but as per https://github.com/facebook/create-react-app/pull/5111#issuecomment-425458687 that was just a proposal and not actually something that landed.

That would allow folks who feel comfortable with the tradeoffs around potentially buggy lazy-loading to opt-in to using skipWaiting: true, and get a quicker update flow.

I've filed separate issue to track the addition of that config file: https://github.com/facebook/create-react-app/issues/5359

frederikhors commented 5 years ago

I'm in favor of adding a cra.config.js for these config and others, overriding default ones!

At first I thought it could already be done.

andidev commented 5 years ago

@mymattcarroll

Can the skipWaiting: true option be applied without ejecting?

This is the hacky way I had to do it install replace-in-file

npm install --save-dev replace-in-file

create a file in the root called hack-add-skipWaiting-true-to-react-script.js UPDATE Changed webpack-config.prod.js to webpack-config.js since the file is renamed in current version

'use strict';
const replace = require('replace-in-file');

try {
    console.log('Adding skipWaiting: true to react-script webpack-config.js');
    replace.sync({
        files: 'node_modules/react-scripts/config/webpack.config.js',
        from: /clientsClaim: true,$/gm,
        to: (match) => {
            return match + ' skipWaiting: true,';
        },
    });
} catch (e) {
    console.log('Something went wrong when trying to add skipWaiting: true to react-script webpack-config.js', e);
    process.exit();
}

Add it as a postinstall script to your package.json

{
   ...
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "postinstall": "node hack-add-skipWaiting-true-to-react-script.js"
  }
}

run npm install and skipWaiting should now be set to true

mymattcarroll commented 5 years ago

Very sneaky @andidev ;)

I have rolled back to react-scripts@1.1.5 for now in the hope #5369 gets accepted.

gabrielmicko commented 5 years ago

If you use react-app-rewired it is fairly easy to achieve this. I can post it if somebody wants it.

kevinOriginal commented 5 years ago

If you use react-app-rewired it is fairly easy to achieve this. I can post it if somebody wants it.

That'd be good but isn't react-app-wired deprecated on CRA v2.0?

FezVrasta commented 5 years ago

@kevinOriginal nope, the message on their repo is confusing. It works just fine, it's just that the utilities used to inject your own configuration work just on V1. But you can either write the code yourself or use the ones provided by customize-cra

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

FezVrasta commented 5 years ago

What's the point of this stale bot? Why should you close an issue if it's waiting to be addressed?

jadbox commented 5 years ago

Any updates here? This seems far too confusing to the 'average use-case' of developers wanting to enable SW to just allow for PWA behavior on mobile. My recommendation is to make SW non-cache friendly by-default to getting cache-stuck.

jadbox commented 5 years ago

I've got my app somewhat working with CRA2 via following "Offer a page reload for users": https://developers.google.com/web/tools/workbox/guides/advanced-recipes

However, in order to send a message to CRA2's auto-generated SW, I use an npm script to append the below lines to the created worker after its built:

self.addEventListener('message', (event) => {
  if (!event.data){
    return;
  }

  switch (event.data) {
    case 'skipWaiting':
      self.skipWaiting();
      break;
    default:
      // NOOP
      break;
  }
});

I'd recommend adding this into the default generated SW as this technique is considered best practice for updating SW apps.

techyrajeev commented 5 years ago

If you use react-app-rewired it is fairly easy to achieve this. I can post it if somebody wants it.

Yes please

techyrajeev commented 5 years ago

I've got my app somewhat working with CRA2 via following "Offer a page reload for users": https://developers.google.com/web/tools/workbox/guides/advanced-recipes

However, in order to send a message to CRA2's auto-generated SW, I use an npm script to append the below lines to the created worker after its built:

self.addEventListener('message', (event) => {
  if (!event.data){
    return;
  }

  switch (event.data) {
    case 'skipWaiting':
      self.skipWaiting();
      break;
    default:
      // NOOP
      break;
  }
});

I'd recommend adding this into the default generated SW as this technique is considered best practice for updating SW apps.

Can you please share how you did it? @jadbox

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

FezVrasta commented 5 years ago

Can you guys just disable this stupid bot please?

kevinsperrine commented 5 years ago

FWIW, I wrote a simple craco plugin called craco-workbox to handle this in CRA2 until #5369 gets merged.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

frederikhors commented 5 years ago

No, @stale.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

crux153 commented 5 years ago

No.

I don't understand the purpose of this bot :(

sky93 commented 5 years ago

By now what is the best way to make skipWaiting true?

FezVrasta commented 5 years ago

I guess customize-cra is the way to go for now.

EddiG commented 5 years ago

@sky93 With CRA v3 you can post a message SKIP_WAITING to the service worker to trigger skip waiting.

// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";

ReactDOM.render(<App />, document.getElementById("root"));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.register({
  onUpdate: registration => {
    const waitingServiceWorker = registration.waiting

    if (waitingServiceWorker) {
      waitingServiceWorker.addEventListener("statechange", event => {
        if (event.target.state === "activated") {
          window.location.reload()
        }
      });
      waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
    }
  }
});

But usualy you want ot ask user before doing reload. I used wrapping service worker registration into the React context:

import React from "react";
import * as serviceWorker from "./serviceWorker";

const ServiceWorkerContext = React.createContext();

function ServiceWorkerProvider(props) {
  const [waitingServiceWorker, setWaitingServiceWorker] = React.useState(null);
  const [assetsUpdateReady, setAssetsUpdateReady] = React.useState(false);
  const [assetsCached, setAssetsCached] = React.useState(false);

  const value = React.useMemo(
    () => ({
      assetsUpdateReady,
      assetsCached,
      // Call when the user confirm update of application and reload page
      updateAssets: () => {
        if (waitingServiceWorker) {
          waitingServiceWorker.addEventListener("statechange", event => {
            if (event.target.state === "activated") {
              window.location.reload()
            }
          });

          waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
        }
      }
    }),
    [assetsUpdateReady, assetsCached, waitingServiceWorker]
  );

  // Once on component mounted subscribe to Update and Succes events in 
  // CRA's service worker wrapper
  React.useEffect(() => {
    serviceWorker.register({
      onUpdate: registration => {
        setWaitingServiceWorker(registration.waiting);
        setAssetsUpdateReady(true);
      },
      onSuccess: () => {
        setAssetsCached(true);
      }
    });
  }, []);

  return <ServiceWorkerContext.Provider value={value} {...props} />;
}

function useServiceWorker() {
  const context = React.useContext(ServiceWorkerContext);

  if (!context) {
    throw new Error(
      "useServiceWorker must be used within a ServiceWorkerProvider"
    );
  }

  return context;
}

export { ServiceWorkerProvider, useServiceWorker };

The only additional change required in the serviceWorker.js file of CRA if you want to register service worker from the React application. You need to get rid of the window.onload event waiting in the register function :

// serviceWorker.js
export function register(config) {
  if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
    // The URL constructor is available in all browsers that support SW.
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
    if (publicUrl.origin !== window.location.origin) {
      // Our service worker won't work if PUBLIC_URL is on a different origin
      // from what our page is served on. This might happen if a CDN is used to
      // serve assets; see https://github.com/facebook/create-react-app/issues/2374
      return;
    }

    // We are not waiting for window's load event as it was for the create-react-app template
    // because we register a service worker in the React app that runs after window loaded
    // and the load event already was emitted.
    const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;

    if (isLocalhost) {
      // This is running on localhost. Let's check if a service worker still exists or not.
      checkValidServiceWorker(swUrl, config);

      // Add some additional logging to localhost, pointing developers to the
      // service worker/PWA documentation.
      navigator.serviceWorker.ready.then(() => {
        console.log(
          "This web app is being served cache-first by a service " +
            "worker. To learn more, visit http://bit.ly/CRA-PWA"
        );
      });
    } else {
      // Is not localhost. Just register service worker
      registerValidSW(swUrl, config);
    }
  }
}
FezVrasta commented 5 years ago

@EddiG shouldn't the service worker handle the SKIP_WAITING message? I don't see it documented in workbox

EddiG commented 5 years ago

@FezVrasta You can find additional info here (Code in your service worker section). Also, if you run yarn build in CRA3 you see the code at the /build/service-worker.js which is responsible for the handling of SKIP_WAITING message:

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'SKIP_WAITING') {
    self.skipWaiting();
  }
});
NurdinDev commented 5 years ago

@sky93 With CRA v3 you can post a message SKIP_WAITING to the service worker to trigger skip waiting.

// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";

ReactDOM.render(<App />, document.getElementById("root"));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.register({
  onUpdate: registration => {
    const waitingServiceWorker = registration.waiting

    if (waitingServiceWorker) {
      waitingServiceWorker.addEventListener("statechange", event => {
        if (event.target.state === "activated") {
          window.location.reload()
        }
      });
      waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
    }
  }
});

But usualy you want ot ask user before doing reload. I used wrapping service worker registration into the React context:

import React from "react";
import * as serviceWorker from "./serviceWorker";

const ServiceWorkerContext = React.createContext();

function ServiceWorkerProvider(props) {
  const [waitingServiceWorker, setWaitingServiceWorker] = React.useState(null);
  const [assetsUpdateReady, setAssetsUpdateReady] = React.useState(false);
  const [assetsCached, setAssetsCached] = React.useState(false);

  const value = React.useMemo(
    () => ({
      assetsUpdateReady,
      assetsCached,
      // Call when the user confirm update of application and reload page
      updateAssets: () => {
        if (waitingServiceWorker) {
          waitingServiceWorker.addEventListener("statechange", event => {
            if (event.target.state === "activated") {
              window.location.reload()
            }
          });

          waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
        }
      }
    }),
    [assetsUpdateReady, assetsCached, waitingServiceWorker]
  );

  // Once on component mounted subscribe to Update and Succes events in 
  // CRA's service worker wrapper
  React.useEffect(() => {
    serviceWorker.register({
      onUpdate: registration => {
        setWaitingServiceWorker(registration.waiting);
        setAssetsUpdateReady(true);
      },
      onSuccess: () => {
        setAssetsCached(true);
      }
    });
  }, []);

  return <ServiceWorkerContext.Provider value={value} {...props} />;
}

function useServiceWorker() {
  const context = React.useContext(ServiceWorkerContext);

  if (!context) {
    throw new Error(
      "useServiceWorker must be used within a ServiceWorkerProvider"
    );
  }

  return context;
}

export { ServiceWorkerProvider, useServiceWorker };

The only additional change required in the serviceWorker.js file of CRA if you want to register service worker from the React application. You need to get rid of the window.onload event waiting in the register function :

// serviceWorker.js
export function register(config) {
  if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
    // The URL constructor is available in all browsers that support SW.
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
    if (publicUrl.origin !== window.location.origin) {
      // Our service worker won't work if PUBLIC_URL is on a different origin
      // from what our page is served on. This might happen if a CDN is used to
      // serve assets; see https://github.com/facebook/create-react-app/issues/2374
      return;
    }

    // We are not waiting for window's load event as it was for the create-react-app template
    // because we register a service worker in the React app that runs after window loaded
    // and the load event already was emitted.
    const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;

    if (isLocalhost) {
      // This is running on localhost. Let's check if a service worker still exists or not.
      checkValidServiceWorker(swUrl, config);

      // Add some additional logging to localhost, pointing developers to the
      // service worker/PWA documentation.
      navigator.serviceWorker.ready.then(() => {
        console.log(
          "This web app is being served cache-first by a service " +
            "worker. To learn more, visit http://bit.ly/CRA-PWA"
        );
      });
    } else {
      // Is not localhost. Just register service worker
      registerValidSW(swUrl, config);
    }
  }
}

@EddiG the first code when you using skip_wating that means the service worker update himself, right?

EddiG commented 5 years ago

@NuruddinBadawi Please read the documentation (Skip the waiting phase particularly), I can't explain better.

marlonmleite commented 5 years ago

@sky93 With CRA v3 you can post a message SKIP_WAITING to the service worker to trigger skip waiting.

// index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";

ReactDOM.render(<App />, document.getElementById("root"));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.register({
  onUpdate: registration => {
    const waitingServiceWorker = registration.waiting

    if (waitingServiceWorker) {
      waitingServiceWorker.addEventListener("statechange", event => {
        if (event.target.state === "activated") {
          window.location.reload()
        }
      });
      waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
    }
  }
});

But usualy you want ot ask user before doing reload. I used wrapping service worker registration into the React context:

import React from "react";
import * as serviceWorker from "./serviceWorker";

const ServiceWorkerContext = React.createContext();

function ServiceWorkerProvider(props) {
  const [waitingServiceWorker, setWaitingServiceWorker] = React.useState(null);
  const [assetsUpdateReady, setAssetsUpdateReady] = React.useState(false);
  const [assetsCached, setAssetsCached] = React.useState(false);

  const value = React.useMemo(
    () => ({
      assetsUpdateReady,
      assetsCached,
      // Call when the user confirm update of application and reload page
      updateAssets: () => {
        if (waitingServiceWorker) {
          waitingServiceWorker.addEventListener("statechange", event => {
            if (event.target.state === "activated") {
              window.location.reload()
            }
          });

          waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
        }
      }
    }),
    [assetsUpdateReady, assetsCached, waitingServiceWorker]
  );

  // Once on component mounted subscribe to Update and Succes events in 
  // CRA's service worker wrapper
  React.useEffect(() => {
    serviceWorker.register({
      onUpdate: registration => {
        setWaitingServiceWorker(registration.waiting);
        setAssetsUpdateReady(true);
      },
      onSuccess: () => {
        setAssetsCached(true);
      }
    });
  }, []);

  return <ServiceWorkerContext.Provider value={value} {...props} />;
}

function useServiceWorker() {
  const context = React.useContext(ServiceWorkerContext);

  if (!context) {
    throw new Error(
      "useServiceWorker must be used within a ServiceWorkerProvider"
    );
  }

  return context;
}

export { ServiceWorkerProvider, useServiceWorker };

The only additional change required in the serviceWorker.js file of CRA if you want to register service worker from the React application. You need to get rid of the window.onload event waiting in the register function :

// serviceWorker.js
export function register(config) {
  if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
    // The URL constructor is available in all browsers that support SW.
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
    if (publicUrl.origin !== window.location.origin) {
      // Our service worker won't work if PUBLIC_URL is on a different origin
      // from what our page is served on. This might happen if a CDN is used to
      // serve assets; see https://github.com/facebook/create-react-app/issues/2374
      return;
    }

    // We are not waiting for window's load event as it was for the create-react-app template
    // because we register a service worker in the React app that runs after window loaded
    // and the load event already was emitted.
    const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;

    if (isLocalhost) {
      // This is running on localhost. Let's check if a service worker still exists or not.
      checkValidServiceWorker(swUrl, config);

      // Add some additional logging to localhost, pointing developers to the
      // service worker/PWA documentation.
      navigator.serviceWorker.ready.then(() => {
        console.log(
          "This web app is being served cache-first by a service " +
            "worker. To learn more, visit http://bit.ly/CRA-PWA"
        );
      });
    } else {
      // Is not localhost. Just register service worker
      registerValidSW(swUrl, config);
    }
  }
}

This solution has been worked on iOS PWA?

We have severous problems with cache/precache assets on execute PWA in iOS.

sky93 commented 5 years ago

@marlonmleite Not working for me in iOS at all. I have to clear safari cache manually to see new changes :(

riccoski commented 5 years ago

Thanks for the solutions. Works perfect for me on ios. I had to tweak obviously to get it working how I wanted.

andrewBsk commented 5 years ago

Thanks for the solutions. Works perfect for me on ios. I had to tweak obviously to get it working how I wanted.

Can you share tweaks please? Still not able to make it work on iOS as a PWA neither as web app on Safari.

riccoski commented 5 years ago

Thanks for the solutions. Works perfect for me on ios. I had to tweak obviously to get it working how I wanted.

Can you share tweaks please? Still not able to make it work on iOS as a PWA neither as web app on Safari.

I'd recommend posting what you have. And are you posting skip waiting on a button click?

andrewBsk commented 5 years ago

Thanks for the solutions. Works perfect for me on ios. I had to tweak obviously to get it working how I wanted.

Can you share tweaks please? Still not able to make it work on iOS as a PWA neither as web app on Safari.

I'd recommend posting what you have. And are you posting skip waiting on a button click?

No, i just used the following snipped that was shared above. Not sure how to trigger skip waiting on a button click i am afraid.

serviceWorker.register({
  onUpdate: registration => {
    const waitingServiceWorker = registration.waiting

    if (waitingServiceWorker) {
      waitingServiceWorker.addEventListener("statechange", event => {
        if (event.target.state === "activated") {
          window.location.reload()
        }
      });
      waitingServiceWorker.postMessage({ type: "SKIP_WAITING" });
    }
  }
});