Skip to content

Commit 7cb6c03

Browse files
authored
fix(various): NG 10 fixes, Storage & FCM regressions (#2522)
* Use navigator serviceWorker for notifications, as FCM seems to be having trouble with RXJS & Angular * Use more of the `registerX` hacks to work around ngcc tree-shaking. Tapping also seems to help, race condition maybe? * Port the sample app to NG 10 * Add all the firebase packages to the Universal externals, having a bunch of problems with that * Experimenting with overriding the legacy packaging choices of the JS SDK with `ngcc.config` in the sample app, should add to the `ng add` schematic if it proves workable * FCM broke in a minor at some point, getToken now prompts for permission; work around this break for now * Firebase Auth seems to be firing an initial null more often now, add the getRedirectResult work-around for now * Firebase Auth is now failing to load in the server environment entirely, work around by returning `of(null)` * Storage is not firing the last snapshot state before completion, making this API difficult to work with, fixed
1 parent 1bf6cc9 commit 7cb6c03

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2403
-1349
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@angular/fire",
3-
"version": "6.0.2",
3+
"version": "6.0.3",
44
"description": "The official library of Firebase and Angular.",
55
"private": true,
66
"scripts": {
File renamed without changes.

sample/angular.json

+24-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
"aot": true,
2222
"assets": [
2323
"src/favicon.ico",
24-
"src/assets"
24+
"src/assets",
25+
"src/manifest.webmanifest",
26+
"src/firebase-messaging-sw.js"
2527
],
2628
"styles": [
2729
"src/styles.css"
@@ -55,7 +57,9 @@
5557
"maximumWarning": "6kb",
5658
"maximumError": "10kb"
5759
}
58-
]
60+
],
61+
"serviceWorker": true,
62+
"ngswConfigPath": "ngsw-config.json"
5963
}
6064
}
6165
},
@@ -85,7 +89,8 @@
8589
"karmaConfig": "karma.conf.js",
8690
"assets": [
8791
"src/favicon.ico",
88-
"src/assets"
92+
"src/assets",
93+
"src/manifest.webmanifest"
8994
],
9095
"styles": [
9196
"src/styles.css"
@@ -124,9 +129,23 @@
124129
"outputPath": "dist/sample/server",
125130
"main": "server.ts",
126131
"tsConfig": "tsconfig.server.json",
127-
"bundleDependencies": false,
132+
"bundleDependencies": true,
128133
"externalDependencies": [
129-
"@firebase/firestore"
134+
"firebase",
135+
"@firebase/app",
136+
"@firebase/analytics",
137+
"@firebase/app",
138+
"@firebase/auth",
139+
"@firebase/component",
140+
"@firebase/database",
141+
"@firebase/firestore",
142+
"@firebase/functions",
143+
"@firebase/installations",
144+
"@firebase/messaging",
145+
"@firebase/storage",
146+
"@firebase/performance",
147+
"@firebase/remote-config",
148+
"@firebase/util"
130149
]
131150
},
132151
"configurations": {

sample/ngcc.config.js

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
module.exports = {
2+
packages: {
3+
"firebase": {
4+
entryPoints: {
5+
".": { override: { main: undefined, browser: undefined } },
6+
"./analytics": { override: { main: undefined, browser: undefined } },
7+
"./app": {override: { main: undefined, browser: undefined } },
8+
"./auth": {override: { main: undefined, browser: undefined } },
9+
"./database": { override: { main: undefined, browser: undefined } },
10+
"./firestore": { override: { main: undefined, browser: undefined } },
11+
"./functions": { override: { main: undefined, browser: undefined } },
12+
"./installations": { override: { main: undefined, browser: undefined } },
13+
"./storage": { override: { main: undefined, browser: undefined } },
14+
"./performance": { override: { main: undefined, browser: undefined } },
15+
"./remote-config": { override: { main: undefined, browser: undefined } },
16+
},
17+
generateDeepReexports: true
18+
},
19+
"@firebase/analytics": {
20+
entryPoints: { ".": { override : { main: undefined, browser: undefined } } },
21+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
22+
},
23+
"@firebase/app": {
24+
entryPoints: { ".": { override : { main: undefined, browser: undefined } } },
25+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
26+
},
27+
"@firebase/auth": {
28+
entryPoints: { ".": { override : { main: undefined, browser: undefined } } },
29+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
30+
},
31+
"@firebase/component": {
32+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
33+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
34+
},
35+
"@firebase/database": {
36+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
37+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
38+
},
39+
"@firebase/firestore": {
40+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
41+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
42+
},
43+
"@firebase/functions": {
44+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
45+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
46+
},
47+
"@firebase/installations": {
48+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
49+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
50+
},
51+
"@firebase/messaging": {
52+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
53+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
54+
},
55+
"@firebase/storage": {
56+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
57+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
58+
},
59+
"@firebase/performance": {
60+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
61+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
62+
},
63+
"@firebase/remote-config": {
64+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
65+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
66+
},
67+
"@firebase/util": {
68+
entryPoints: { ".": { override: { main: undefined, browser: undefined } } },
69+
ignorableDeepImportMatchers: [ /@firebase\/app-types\/private/ ]
70+
}
71+
}
72+
}

sample/ngsw-config.json

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
3+
"index": "/index.html",
4+
"assetGroups": [
5+
{
6+
"name": "app",
7+
"installMode": "prefetch",
8+
"resources": {
9+
"files": [
10+
"/favicon.ico",
11+
"/index.html",
12+
"/manifest.webmanifest",
13+
"/*.css",
14+
"/*.js"
15+
]
16+
}
17+
}, {
18+
"name": "assets",
19+
"installMode": "lazy",
20+
"updateMode": "prefetch",
21+
"resources": {
22+
"files": [
23+
"/assets/**",
24+
"/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
25+
]
26+
}
27+
}
28+
]
29+
}

sample/package.json

+23-23
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,30 @@
1515
},
1616
"private": true,
1717
"dependencies": {
18-
"@angular/animations": "~9.1.0",
19-
"@angular/common": "~9.1.0",
20-
"@angular/compiler": "~9.1.0",
21-
"@angular/core": "~9.1.0",
18+
"@angular/animations": "~10.0.0",
19+
"@angular/common": "~10.0.0",
20+
"@angular/compiler": "~10.0.0",
21+
"@angular/core": "~10.0.0",
2222
"@angular/fire": "../dist/packages-dist",
23-
"@angular/forms": "~9.1.0",
24-
"@angular/platform-browser": "~9.1.0",
25-
"@angular/platform-browser-dynamic": "~9.1.0",
26-
"@angular/platform-server": "~9.1.0",
27-
"@angular/router": "~9.1.0",
28-
"@angular/service-worker": "~9.1.0",
23+
"@angular/forms": "~10.0.0",
24+
"@angular/platform-browser": "~10.0.0",
25+
"@angular/platform-browser-dynamic": "~10.0.0",
26+
"@angular/platform-server": "~10.0.0",
27+
"@angular/router": "~10.0.0",
28+
"@angular/service-worker": "^10.0.0",
2929
"@nguniversal/express-engine": "~9.1.0",
3030
"firebase": "^7.13.2",
3131
"proxy-polyfill": "^0.3.1",
3232
"rxjs": "~6.5.4",
33-
"tslib": "^1.10.0",
33+
"tslib": "^2.0.0",
3434
"zone.js": "~0.10.2"
3535
},
3636
"devDependencies": {
3737
"@angular-devkit/architect": "~0.901.0",
38-
"@angular-devkit/build-angular": "~0.901.0",
39-
"@angular/cli": "~9.1.0",
40-
"@angular/compiler-cli": "~9.1.0",
41-
"@angular/language-service": "~9.1.0",
38+
"@angular-devkit/build-angular": "~0.1000.0",
39+
"@angular/cli": "~10.0.0",
40+
"@angular/compiler-cli": "~10.0.0",
41+
"@angular/language-service": "~10.0.0",
4242
"@nguniversal/builders": "^9.1.0",
4343
"@types/jasmine": "~3.5.0",
4444
"@types/jasminewd2": "~2.0.3",
@@ -53,15 +53,15 @@
5353
"inquirer": "^6.2.2",
5454
"inquirer-autocomplete-prompt": "^1.0.1",
5555
"jasmine-core": "~3.5.0",
56-
"jasmine-spec-reporter": "~4.2.1",
57-
"karma": "~4.3.0",
56+
"jasmine-spec-reporter": "~5.0.0",
57+
"karma": "~5.0.0",
5858
"karma-chrome-launcher": "~3.1.0",
59-
"karma-coverage-istanbul-reporter": "~2.1.0",
60-
"karma-jasmine": "~2.0.1",
61-
"karma-jasmine-html-reporter": "^1.4.2",
62-
"protractor": "~5.4.3",
59+
"karma-coverage-istanbul-reporter": "~3.0.2",
60+
"karma-jasmine": "~3.3.0",
61+
"karma-jasmine-html-reporter": "^1.5.0",
62+
"protractor": "~7.0.0",
6363
"ts-node": "~8.3.0",
64-
"tslint": "~5.18.0",
65-
"typescript": "~3.7.5"
64+
"tslint": "~6.1.0",
65+
"typescript": "~3.9.5"
6666
}
6767
}

sample/src/app/app.module.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { StorageComponent } from './storage/storage.component';
3131
import { RemoteConfigComponent } from './remote-config/remote-config.component';
3232
import { HomeComponent } from './home/home.component';
3333
import { AuthComponent } from './auth/auth.component';
34+
import { MessagingComponent } from './messaging/messaging.component';
3435

3536
const shouldUseEmulator = () => false;
3637

@@ -42,7 +43,8 @@ const shouldUseEmulator = () => false;
4243
DatabaseComponent,
4344
RemoteConfigComponent,
4445
HomeComponent,
45-
AuthComponent
46+
AuthComponent,
47+
MessagingComponent
4648
],
4749
imports: [
4850
BrowserModule.withServerTransition({ appId: 'serverApp' }),

sample/src/app/auth/auth.component.ts

+20-14
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import { Component, OnInit, OnDestroy } from '@angular/core';
1+
import { Component, OnInit, OnDestroy, PLATFORM_ID } from '@angular/core';
22
import { AngularFireAuth } from '@angular/fire/auth';
3-
import { auth as rawAuth } from 'firebase/app';
3+
import firebase from 'firebase/app';
44
import { Subscription } from 'rxjs';
5-
import { map } from 'rxjs/operators';
5+
import { map, tap } from 'rxjs/operators';
66
import { trace } from '@angular/fire/performance';
7+
import { Inject } from '@angular/core';
8+
import { isPlatformServer } from '@angular/common';
79

810
@Component({
911
selector: 'app-auth',
@@ -19,29 +21,33 @@ import { trace } from '@angular/fire/performance';
1921
})
2022
export class AuthComponent implements OnInit, OnDestroy {
2123

22-
private readonly userDisposable: Subscription;
24+
private readonly userDisposable: Subscription|undefined;
2325

2426
showLoginButton = false;
2527
showLogoutButton = false;
2628

27-
constructor(public readonly auth: AngularFireAuth) {
28-
this.userDisposable = this.auth.authState.pipe(
29-
trace('auth'),
30-
map(u => !!u)
31-
).subscribe(isLoggedIn => {
32-
this.showLoginButton = !isLoggedIn;
33-
this.showLogoutButton = isLoggedIn;
34-
});
29+
constructor(public readonly auth: AngularFireAuth, @Inject(PLATFORM_ID) platformId: object) {
30+
if (!isPlatformServer(platformId)) {
31+
this.userDisposable = this.auth.authState.pipe(
32+
trace('auth'),
33+
map(u => !!u)
34+
).subscribe(isLoggedIn => {
35+
this.showLoginButton = !isLoggedIn;
36+
this.showLogoutButton = isLoggedIn;
37+
});
38+
}
3539
}
3640

3741
ngOnInit(): void { }
3842

3943
ngOnDestroy(): void {
40-
this.userDisposable.unsubscribe();
44+
if (this.userDisposable) {
45+
this.userDisposable.unsubscribe();
46+
}
4147
}
4248

4349
login() {
44-
this.auth.signInWithPopup(new rawAuth.GoogleAuthProvider());
50+
this.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
4551
}
4652

4753
logout() {

sample/src/app/home/home.component.ts

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { FirebaseApp } from '@angular/fire';
1111
<app-remote-config></app-remote-config>
1212
<app-storage></app-storage>
1313
<app-auth></app-auth>
14+
<app-messaging></app-messaging>
1415
`,
1516
styles: [``]
1617
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { MessagingComponent } from './messaging.component';
4+
5+
describe('MessagingComponent', () => {
6+
let component: MessagingComponent;
7+
let fixture: ComponentFixture<MessagingComponent>;
8+
9+
beforeEach(async(() => {
10+
TestBed.configureTestingModule({
11+
declarations: [ MessagingComponent ]
12+
})
13+
.compileComponents();
14+
}));
15+
16+
beforeEach(() => {
17+
fixture = TestBed.createComponent(MessagingComponent);
18+
component = fixture.componentInstance;
19+
fixture.detectChanges();
20+
});
21+
22+
it('should create', () => {
23+
expect(component).toBeTruthy();
24+
});
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Component, OnInit } from '@angular/core';
2+
import { AngularFireMessaging } from '@angular/fire/messaging';
3+
import { trace } from '@angular/fire/performance';
4+
import { Observable, fromEvent } from 'rxjs';
5+
import { tap, map, filter } from 'rxjs/operators';
6+
import * as firebase from 'firebase/app';
7+
import 'firebase/messaging';
8+
import { SwPush } from '@angular/service-worker';
9+
10+
@Component({
11+
selector: 'app-messaging',
12+
template: `
13+
<p>
14+
Messaging!
15+
{{ token$ | async | json }}
16+
{{ message$ | async | json }}
17+
<button (click)="request()" *ngIf="showRequest">Request FCM token</button>
18+
</p>
19+
`,
20+
styles: []
21+
})
22+
export class MessagingComponent implements OnInit {
23+
24+
token$: Observable<any>;
25+
message$: Observable<any>;
26+
showRequest = false;
27+
28+
constructor(public readonly messaging: AngularFireMessaging, swPush: SwPush) {
29+
messaging.usePublicVapidKey('BIDPctnXHQDIjcOXxDS6qQcz-QTws7bL8v7UPgFnS1Ky5BZL3jS3-XXfxwRHmAUMOk7pXme7ttOBvVoIfX57PEo').then(() => {
30+
this.message$ = messaging.messages;
31+
this.token$ = messaging.tokenChanges.pipe(
32+
trace('token'),
33+
tap(token => this.showRequest = !token)
34+
);
35+
});
36+
}
37+
38+
ngOnInit(): void {
39+
}
40+
41+
request() {
42+
this.messaging.requestPermission.subscribe(console.log, console.error);
43+
}
44+
45+
}

0 commit comments

Comments
 (0)