9

Now I know there are a million posts about No Provider for such and such service, I know it needs to go in the providers please read my entire post.

Basically I am trying to use SwUpdate to check to see if there is an update if so, refresh the browser:

import { SwUpdate } from '@angular/service-worker';
...

export class ...

constructor(
    private _swUp: SwUpdate
){} 


ngOnInit() {
    this.checkForUpdate();
}

checkForUpdate() {
    if (this._swUp.isEnabled) {
       this._swUp.available
           .subscribe(() => {
               window.location.reload();
           });
    }
}

now I have registered my serviceworker:

import { ServiceWorkerModule } from '@angular/service-worker'; 
...

imports: [
    environment.production ? ServiceWorkerModule.register('ngsw-worker.js') : [],
]

now when I run my app I get this error:

NullInjectorError: No provider for SwUpdate!

so obviously I try and add it to the providers array in my component module:

import { ServiceWorkerModule, SwUpdate } from '@angular/service-worker'; 
...

imports: [
    environment.production ? ServiceWorkerModule.register('ngsw-worker.js') : [],
],
providers: [
    SwUpdate
]

now this should work but now this time when I run the application I get the following error:

NullInjectorError: No provider for NgswCommChannel!

Now when I try to import NgswCommChannel I get an error saying it does not exist in @angular/service-worker;

I've tried googling around but I cannot find a reference to NgswCommChanel anywhere...

So my question is how can I fix this, or how can I properly use SwUpdate ??

any help would be appreciated

EDIT

I have also tried to do it the EXACT same way it is done in the official angular docs and it is giving me the same error:

constructor(
    updates: SwUpdate
) {
    updates.available
        .subscribe(() => {
            updates.activateUpdate()
                .then(() => document.location.reload());
        });
}

EDIT 2 This is what I get when I run ng -v

Angular CLI: 1.7.4
Node: 10.15.1
OS: win32 x64
Angular: 5.1.2
... animations, common, compiler, compiler-cli, core, forms
... http, platform-browser, platform-browser-dynamic
... platform-server, router

@angular/cli: 1.7.4
@angular/service-worker: 7.2.7
@angular-devkit/build-optimizer: 0.3.2
@angular-devkit/core: 0.3.2
@angular-devkit/schematics: 0.0.40
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.10.2
typescript: 2.4.2
webpack: 3.11.0

EDIT 3

Upon further investigation it seems as if you can not use SwUpdate when running your project locally, I saw this article angular-pwa-pitfalls and there solution is to install ng-toolkit, but this just allows you to build your project and then run a mock server, which is pointless because ill lose the ability to develop locally without building the project everytime.

EDIT 4

I changed my app.module.ts to register the service worker:

ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })

but now I'm getting a whole new bunch of errors

enter image description here

Any other suggestions would be great.

Thanks

Smokey Dawson
  • 8,827
  • 19
  • 77
  • 152

4 Answers4

16

Your issue is in the app.module.ts.

You need to import your service worker like this:

imports: [
    ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
],

The code you had before was only including the module when you were in production mode, so during development it wasn't including the module at all.

EDIT:

Inside my app.component.ts I have:

constructor(private swUpdate: SwUpdate) { }

ngAfterViewInit() {
  if (this.swUpdate.isEnabled) {
    this.swUpdate.available
      .subscribe(() => {
        this.swUpdate
          .activateUpdate()
          .then(() => {
            window.location.reload();
          });
      });
  }
}

EDIT:

As per your comment, updating to latest version of Angular fixed your issue, it's nice they've made upgrading so simple now :)

Wesley Coetzee
  • 4,768
  • 3
  • 27
  • 45
  • Did you add the service worker with the command: `ng add @angular/pwa --project *project-name*`? As that command adds the required steps/commands within the app – Wesley Coetzee Mar 05 '19 at 06:28
  • No I did it manually by following this [tutorial](https://medium.com/@nsmirnova/creating-pwa-with-angular-5-part-2-progressifying-the-application-449e3a706129) my project is Angular 5 and does not support `ng add` – Smokey Dawson Mar 05 '19 at 21:58
  • I upgraded my project to angular 7 and ran ng add @angular/pwa and that solved my problem. – Smokey Dawson Mar 06 '19 at 02:02
  • If you edit your answer to say to update to a later version of angular and run `ng add @angular/pwa` I will mark this answer as correct since it pointed my in the right direction – Smokey Dawson Mar 06 '19 at 02:09
  • @SmokeyDawson I've updated my answer, it's really nice they've made upgrading so simple now :) – Wesley Coetzee Mar 06 '19 at 08:39
  • 1
    where is `: []`coming from, there is no ternary operator in front as I can see, It's throwing error for me. – ishandutta2007 Apr 22 '19 at 06:56
8

For the ones who are getting this error when trying to write unit tests the solution is to add the ServiceWorkerModule to the imports array with the enable to false option when configuring the TestBed:

TestBed.configureTestingModule({
  declarations: [ MyComponent ],
  imports: [
    ServiceWorkerModule.register('ngsw-worker.js', { enabled: false })
  ]
})
.compileComponents();
vhbazan
  • 1,240
  • 1
  • 17
  • 26
1

After much research it seems like it was an issue with angular 5.2.1 so..

I upgraded my project to angular 7, ran ng add @angular/pwa and that solved my problem!

Smokey Dawson
  • 8,827
  • 19
  • 77
  • 152
-2

Try below code, Add update into ngOnInit() method.

 constructor(private updates: SwUpdate) {}

 ngOnInit(){
     this.updates.available
    .subscribe(() => {
        this.updates.activateUpdate()
            .then(() => document.location.reload());
    });
 }       
Akil Makda
  • 373
  • 1
  • 3
  • 9