diff --git a/packages/service-worker/package.json b/packages/service-worker/package.json index 7a9c1dd2f2..e945daa756 100644 --- a/packages/service-worker/package.json +++ b/packages/service-worker/package.json @@ -12,7 +12,8 @@ "tslib": "^1.7.1" }, "peerDependencies": { - "@angular/core": "0.0.0-PLACEHOLDER" + "@angular/core": "0.0.0-PLACEHOLDER", + "@angular/common": "0.0.0-PLACEHOLDER" }, "repository": { "type": "git", diff --git a/packages/service-worker/rollup.config.js b/packages/service-worker/rollup.config.js index 6242de44c3..e152afa141 100644 --- a/packages/service-worker/rollup.config.js +++ b/packages/service-worker/rollup.config.js @@ -11,6 +11,7 @@ const sourcemaps = require('rollup-plugin-sourcemaps'); const globals = { '@angular/core': 'ng.core', + '@angular/common': 'ng.common', 'rxjs/BehaviorSubject': 'Rx', 'rxjs/ConnectableObservable': 'Rx', diff --git a/packages/service-worker/src/low_level.ts b/packages/service-worker/src/low_level.ts index 6d46b7264a..cae373904c 100644 --- a/packages/service-worker/src/low_level.ts +++ b/packages/service-worker/src/low_level.ts @@ -6,7 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {Injectable} from '@angular/core'; +import {isPlatformBrowser} from '@angular/common'; +import {Inject, Injectable, PLATFORM_ID} from '@angular/core'; import {BehaviorSubject} from 'rxjs/BehaviorSubject'; import {Observable} from 'rxjs/Observable'; import {ConnectableObservable} from 'rxjs/observable/ConnectableObservable'; @@ -86,8 +87,11 @@ export class NgswCommChannel { */ readonly events: Observable; - constructor(private serviceWorker: ServiceWorkerContainer|undefined) { - if (!serviceWorker) { + constructor( + private serviceWorker: ServiceWorkerContainer|undefined, + @Inject(PLATFORM_ID) platformId: string) { + if (!serviceWorker || !isPlatformBrowser(platformId)) { + this.serviceWorker = undefined; this.worker = this.events = this.registration = errorObservable(ERR_SW_NOT_SUPPORTED); } else { const controllerChangeEvents = diff --git a/packages/service-worker/src/module.ts b/packages/service-worker/src/module.ts index 297a4faff5..a325762aa7 100644 --- a/packages/service-worker/src/module.ts +++ b/packages/service-worker/src/module.ts @@ -6,7 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {APP_INITIALIZER, ApplicationRef, Inject, InjectionToken, Injector, ModuleWithProviders, NgModule} from '@angular/core'; +import {isPlatformBrowser} from '@angular/common'; +import {APP_INITIALIZER, ApplicationRef, Inject, InjectionToken, Injector, ModuleWithProviders, NgModule, PLATFORM_ID} from '@angular/core'; import {Observable} from 'rxjs/Observable'; import {filter as op_filter} from 'rxjs/operator/filter'; import {take as op_take} from 'rxjs/operator/take'; @@ -24,10 +25,12 @@ export abstract class RegistrationOptions { export const SCRIPT = new InjectionToken('NGSW_REGISTER_SCRIPT'); export function ngswAppInitializer( - injector: Injector, script: string, options: RegistrationOptions): Function { + injector: Injector, script: string, options: RegistrationOptions, + platformId: string): Function { const initializer = () => { const app = injector.get(ApplicationRef); - if (!('serviceWorker' in navigator) || options.enabled === false) { + if (!(isPlatformBrowser(platformId) && ('serviceWorker' in navigator) && + options.enabled !== false)) { return; } const onStable = @@ -51,8 +54,10 @@ export function ngswAppInitializer( return initializer; } -export function ngswCommChannelFactory(opts: RegistrationOptions): NgswCommChannel { - return new NgswCommChannel(opts.enabled !== false ? navigator.serviceWorker : undefined); +export function ngswCommChannelFactory( + opts: RegistrationOptions, platformId: string): NgswCommChannel { + return new NgswCommChannel( + opts.enabled !== false ? navigator.serviceWorker : undefined, platformId); } /** @@ -75,11 +80,15 @@ export class ServiceWorkerModule { providers: [ {provide: SCRIPT, useValue: script}, {provide: RegistrationOptions, useValue: opts}, - {provide: NgswCommChannel, useFactory: ngswCommChannelFactory, deps: [RegistrationOptions]}, + { + provide: NgswCommChannel, + useFactory: ngswCommChannelFactory, + deps: [RegistrationOptions, PLATFORM_ID] + }, { provide: APP_INITIALIZER, useFactory: ngswAppInitializer, - deps: [Injector, SCRIPT, RegistrationOptions], + deps: [Injector, SCRIPT, RegistrationOptions, PLATFORM_ID], multi: true, }, ], diff --git a/packages/service-worker/test/comm_spec.ts b/packages/service-worker/test/comm_spec.ts index 9788c9b1a7..3d6f27e191 100644 --- a/packages/service-worker/test/comm_spec.ts +++ b/packages/service-worker/test/comm_spec.ts @@ -20,12 +20,12 @@ export function main() { let comm: NgswCommChannel; beforeEach(() => { mock = new MockServiceWorkerContainer(); - comm = new NgswCommChannel(mock as any); + comm = new NgswCommChannel(mock as any, 'browser'); }); describe('NgswCommsChannel', () => { it('can access the registration when it comes before subscription', (done: DoneFn) => { const mock = new MockServiceWorkerContainer(); - const comm = new NgswCommChannel(mock as any); + const comm = new NgswCommChannel(mock as any, 'browser'); const regPromise = mock.getRegistration() as any as MockServiceWorkerRegistration; mock.setupSw(); @@ -34,13 +34,18 @@ export function main() { }); it('can access the registration when it comes after subscription', (done: DoneFn) => { const mock = new MockServiceWorkerContainer(); - const comm = new NgswCommChannel(mock as any); + const comm = new NgswCommChannel(mock as any, 'browser'); const regPromise = mock.getRegistration() as any as MockServiceWorkerRegistration; comm.registration.subscribe(reg => { done(); }); mock.setupSw(); }); + it('is disabled for platform-server', () => { + const mock = new MockServiceWorkerContainer(); + const comm = new NgswCommChannel(mock as any, 'server'); + expect(comm.isEnabled).toEqual(false); + }); }); describe('SwPush', () => { let push: SwPush; @@ -72,7 +77,7 @@ export function main() { expect(() => TestBed.get(SwPush)).not.toThrow(); }); describe('with no SW', () => { - beforeEach(() => { comm = new NgswCommChannel(undefined); }); + beforeEach(() => { comm = new NgswCommChannel(undefined, 'browser'); }); it('can be instantiated', () => { push = new SwPush(comm); }); it('does not crash on subscription to observables', () => { push = new SwPush(comm); @@ -166,7 +171,7 @@ export function main() { expect(() => TestBed.get(SwUpdate)).not.toThrow(); }); describe('with no SW', () => { - beforeEach(() => { comm = new NgswCommChannel(undefined); }); + beforeEach(() => { comm = new NgswCommChannel(undefined, 'browser'); }); it('can be instantiated', () => { update = new SwUpdate(comm); }); it('does not crash on subscription to observables', () => { update = new SwUpdate(comm); diff --git a/packages/service-worker/test/integration_spec.ts b/packages/service-worker/test/integration_spec.ts index de069c3534..3a500c1054 100644 --- a/packages/service-worker/test/integration_spec.ts +++ b/packages/service-worker/test/integration_spec.ts @@ -80,7 +80,7 @@ export function main() { async_beforeEach(async() => { // Fire up the client. mock = new MockServiceWorkerContainer(); - comm = new NgswCommChannel(mock as any); + comm = new NgswCommChannel(mock as any, 'browser'); scope = new SwTestHarnessBuilder().withServerState(server).build(); driver = new Driver(scope, scope, new CacheDatabase(scope, scope)); diff --git a/packages/service-worker/tsconfig-build.json b/packages/service-worker/tsconfig-build.json index 6c67f34405..9e6c2b0ad2 100644 --- a/packages/service-worker/tsconfig-build.json +++ b/packages/service-worker/tsconfig-build.json @@ -5,7 +5,8 @@ "baseUrl": ".", "rootDir": ".", "paths": { - "@angular/core": ["../../dist/packages/core"] + "@angular/core": ["../../dist/packages/core"], + "@angular/common": ["../../dist/packages/common"] }, "outDir": "../../dist/packages/service-worker" },