angular: bug(service-worker): does not start/install (zone not stabilizing)

I’m submitting a…


[ ] Regression (a behavior that used to work and stopped working in a new release)
[X] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

Service worker does not start/install.

Expected behavior

Service worker should always start/install.

Minimal reproduction of the problem with instructions

  • create new project ng new test-service-worker --service-worker
  • add this code to the app.component’s constructor: setInterval(function() { console.log('test'); }, 1000);
  • build app ng build --prod
  • service worker will never start/install

Environment


Angular version: 5.1.0
CLI: 1.6.0

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 25
  • Comments: 51 (18 by maintainers)

Commits related to this issue

Most upvoted comments

I run into the same problem when I use interval from import { interval } from 'rxjs/observable/interval'; like in the service worker docs.

As a workaround I did that

this.ngZone.runOutsideAngular(() => {
  interval(ms).subscribe(() => {
    this.ngZone.run(() => this.updates.checkForUpdate());
  });
});

and everything works fine now, but this is just a workaround.

By the way, awesome service worker integration, big thx for that!

@btroncone sure. I have a ServiceWorkerService that is injected into my main component. Here is the code from the service’s constructor:

if (environment.production && 'serviceWorker' in navigator) {
  navigator.serviceWorker.getRegistration()
    .then(active => !active && navigator.serviceWorker.register('/ngsw-worker.js'))
    .catch(console.error)
}

This is sooooo ugly. Just spent two hours to find out that the documentation is recommending the not-working “solution”.

I’m fine with running things outside angular zone, I don’t even care whether this is a workaround or not. But, for the god’s sake, I ask for all the people who will come to this issue some day, fix the documentation!

Better it recommends nothing than something that is known to be not working since already half a year.

Hello @Ploppy3,

There is an ongoing investigation into this issue (which affects far more than service worker - the Angular zone never becomes stable in such an app).

With code comes from angular-cli#8779, also works. That’s, wrap the interval part after the application is stable. thanks @dirand

export class AppComponent implements OnInit {
  title = 'app';

  constructor(private applicationRef: ApplicationRef) {
  }

  ngOnInit() {

    this.applicationRef.isStable.subscribe((s) => { // #1
      if (s) { // #2
        setInterval(t => { console.log('Ping')}, 500);
      } // #3
    }); // #4
    // If you uncomment 1-4 - service-worker will not run

    this.applicationRef.isStable.subscribe(t => {
      console.log('App stable: ' + t);
    });
  }
}

@btroncone Correct 😃

@smnbbrv You can open an issue regarding the documentation.

Also, only the setTimeout or setInterval statements should run outside the zone, the given function should run in the zone and therefore it does not affect your app.

this.ngZone.runOutsideAngular(() => {
  interval(1000).subscribe(() => {
    this.ngZone.run(() => {
      // put your usual code here
    });
  });
});

Ran into this issue on a new Angular 6.1.4 app. Service Worker doesn’t install when rxjs’ interval is used as advised in the official documentation. When it’s commented out, everything works as expected.

Is there any sign of an official workaround/fix for this issue? It seems odd to me that the docs would recommend this approach if it doesn’t work. It seems like there should be some kind of note in the docs that warns about this behavior.

@alxhub I’ve created a reproduction repo here. You can see that the NGSW doesn’t register here.

Once #21842 lands, we could consider changing the default strategy to registering once stable or when a certain amont of time passes (whichever comes first).

@sean-nicholas So you still include ServiceWorkerModule.register(script, options) in your main app module for the rest of the services? Even though the registration of the script fails the rest works perfectly?

Thanks for your help!

@sean-nicholas If you don’t mind me asking, how are you managing registering for available updates without the use of the SwUpdate service?

@btroncone, I have created a PR https://github.com/angular/angular/pull/21842 to support more strategy. but as @sean-nicholas said, you can register by yourself.

@btroncone Maybe you have somewhere an interval or a long running timeout. Nevertheless, my fix was to register the service worker by myself: navigator.serviceWorker.register('/ngsw-worker.js') Just check if you are in production, the browser supports sw and no sw is currently active.

@Splaktar, I think the reason is firebase auth make a very very long setTimeout to do proactive token refresh. (more than 200000ms), so maybe service worker need to provide a manually register way, I will do a little more research.