Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Allow for service worker update without closing app #7237

Open
jamesmfriedman opened this issue Jun 17, 2019 · 7 comments
Open

Proposal: Allow for service worker update without closing app #7237

jamesmfriedman opened this issue Jun 17, 2019 · 7 comments
Assignees

Comments

@jamesmfriedman
Copy link
Contributor

Relates to #3534

Proposal

Developers should be able to manually update their service worker on request

Current Behavior

Service workers update lazily, sometimes on navigation. Sometimes when the app reloads. In the case of an iOS PWA, the answer it VERY unpredictable. As of iOS 12.2, the app context is frozen and resumes whenever you reopen, which means your service worker will likely not be updated until the app unloads itself which could be anywhere between 24 hours and 2 weeks.

Working example

  • With minimal tweaks, I was able to get this working in my own project
  • I added an "immediate" option to the serviceWorker.register config
  • For my iOS PWA, I used the page visibility api to call serviceWorker.register({immediate: true}) whenever the page becomes active again. Works like a charm.

Modifications to the register function

export function register(config?: 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 as { env: { [key: string]: string } }).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;
    }
     
    // PULL OUT THIS FUNCTION SO IT CAN BE REUSED
    const doRegister = () => {
      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 https://bit.ly/CRA-PWA'
          );
        });
      } else {
        // Is not localhost. Just register service worker
        registerValidSW(swUrl, config);
      }
    };

    // EITHER CALL REGISTER IMMEDIATELY, OR WAIT FOR WINDOW LOAD (CURRENT BEHAVIOR)
    if (config && config.immediate) {
      doRegister();
    } else {
      window.addEventListener('load', doRegister);
    }
  }
}
function registerValidSW(swUrl: string, config?: Config) {
  if (config && config.immediate) {
      // TO MY SURPRISE, THESE TWO LINES RE-TRIGGERED ALL OF THE APPROPRIATE BEHAVIOR
    navigator.serviceWorker.getRegistration(swUrl).then(registration => {
      registration && registration.update();
    });
  } else {
    navigator.serviceWorker
      .register(swUrl)
      .then(registration => {
                //... REST IS THE SAME
       })

Why?

Usually I wouldn't bother proposing stuff like this, but it only adds about 6 new lines of code (rerranges a bit more) and gives the developer more control over the update cycle of their app.

@jamesmfriedman jamesmfriedman changed the title Proposal: Allow for live service worker update without closing app Proposal: Allow for service worker update without closing app Jun 17, 2019
@mrmckeb
Copy link
Contributor

mrmckeb commented Jun 23, 2019

Hi @jamesmfriedman, as you can control this file yourself, this doesn't need a change on our end.

Do you mean that you think we should turn this on by default for all new projects?

@mrmckeb mrmckeb self-assigned this Jun 23, 2019
@jamesmfriedman
Copy link
Contributor Author

That is correct. I don’t know that many people really look or try to understand what’s going on with the service worker file. Defaulting to this just gives a path to live update the app which would otherwise have to be figured out by the individual developers. So yes, if you like the solution I think just updating the future generated templated file would be a nice value add.

@mrmckeb
Copy link
Contributor

mrmckeb commented Jun 24, 2019

@ianschmitz, any thoughts on this one? I'm a little concerned about further-complicating the base service worker as we know a lot of people already find it confusing.

@goldylucks
Copy link

this approach makes a lot of sense to me. I might be way off here, but wouldn't switching to a more workbox-window approach would make this easier?

@rizwan-ishtiaq
Copy link

It is really nice suggestion. CRA should provide someway to check for updates in SW
By the way @jamesmfriedman if your app is using router (e-g BrowserRouter) it can easily listen on history and when history change, app can trigger update check using immediate=true
There will be no need to add extra (page visibility api) logic - if your app don't need this.

@jamesmfriedman
Copy link
Contributor Author

Thanks @rizwan-ishtiaq. I have to say this is been working like a champ and has solved most of my service worker update problems.

@scienfier
Copy link

works great on computer chrome browsers. Tested on Iphone 11 and android. Both failed. Still need to close the tab then open again to get the updates!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants