Skip to content

Commit 3e5518e

Browse files
committed
Starting on upgrade guide
1 parent 1233a1c commit 3e5518e

File tree

3 files changed

+181
-5
lines changed

3 files changed

+181
-5
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ AngularFire doesn't follow Angular's versioning as Firebase also has breaking ch
6161

6262
| Angular | Firebase | AngularFire |
6363
| --------|----------|--------------|
64-
| 12 | 9 | ^7.0 |
64+
| 12 | [9 <sup>beta</sup>](https://firebase.google.com/docs/web/learn-more#modular-version) | [^7.0 <sup>beta</sup>](https://github.com/angular/angularfire/tree/exp) |
65+
| 12 | 7,8 | ^6.1.5 |
6566
| 11 | 7,8 | ^6.1 |
6667
| 10 | 8 | ^6.0.4 |
6768
| 10 | 7 | ^6.0.3 |

docs/version-7-upgrade.md

Lines changed: 176 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,179 @@
22

33
Intended to be run with Angular 12, AngularFire 7.0 allows you to take full advtange of the new tree-shakable Firebase JS SDK (v9) while also providing a compatible expirience with the prior API.
44

5-
**TBD**
5+
## Compatibility mode
6+
7+
AngularFire v7.0 has a compatibility layer that supports the AngularFire v6.0 API. Just change your imports from `@angular/fire/*` to `@angular/fire/compat/*` and `firebase/*` to `firebase/compat/*`.
8+
9+
While not as tree-shakable as the new modular SDK, this allows you to upgrade and take advantage of the benefits of the new SDK ASAP.
10+
11+
## Modular SDK
12+
13+
### Initialization
14+
15+
In order to better support the tree-shakability introduced in Firebase v9 & to reduce the maintence required when the JS SDK adds new configuration flags, AngularFire providers now take a factory for a fully instantiated instance of the SDK you'd like to inject.
16+
17+
**Before:**
18+
```ts
19+
@NgModule({
20+
imports: [
21+
AngularFire.initalizeApp(config),
22+
AngularFirestoreModule.enablePersistence({ synchronizeTabs: true }),
23+
AngularFireStorageModule,
24+
],
25+
providers: [
26+
{ provide: SETTINGS, useValue: { ignoreUndefinedProperties: true } },
27+
{ provide: USE_EMULATOR, useValue: ['localhost', 8080] },
28+
],
29+
})
30+
```
31+
32+
**Modular SDK:**
33+
```ts
34+
@NgModule({
35+
imports: [
36+
provideFirebaseApp(() => initializeApp(config)),
37+
provideFirestore(() => {
38+
const firestore = getFirestore();
39+
connectEmulator(firestore, 'localhost', 8080);
40+
enableIndexedDbPersistence(firestore);
41+
return firestore;
42+
}),
43+
provideStorage(() => getStorage()),
44+
],
45+
providers: [
46+
{ provide: FIRESTORE_SETTINGS, useValue: { ignoreUndefinedProperties: true } },
47+
],
48+
})
49+
```
50+
51+
### Injecting services
52+
53+
Before when you injected Firebase JS SDK services into AngularFire they would be lazy-loaded and a promise-proxy would be returned to you. In AngularFire v7 you get the intiated service directly. We no longer lazy load for you.
54+
55+
```ts
56+
import { FirebaseApp } from '@angular/fire';
57+
import { Firestore } from '@angular/fire/firestore';
58+
import { doc, onSnapshot } from 'firebase/firestore';
59+
60+
@Component({})
61+
export class Foo {
62+
constructor(
63+
app: FirebaseApp,
64+
firestore: Firestore, // Injects the instantiated Firestore instance
65+
) {
66+
// You can directly operate on the instance with the JS SDK
67+
// NOTE: you will have to handle change-detection yourself
68+
onSnapshot(doc(firestore, 'foo/1'), snap => {
69+
// ...
70+
});
71+
}
72+
}
73+
```
74+
75+
### Class methods
76+
77+
AngularFire no longer provides observables and functions as class methods, everthing is a implemented as a pure function that can be tree-shaken.
78+
79+
<table>
80+
<thead>
81+
<tr>
82+
<th colspan="2">v6 / Compat</th>
83+
<th>v7 Modular</th>
84+
</tr>
85+
</thead>
86+
<tbody>
87+
<tr>
88+
<td rowspan="3">AngularFirestore</td>
89+
<td>collection</td>
90+
<td class="highlight highlight-source-ts"><pre>import { collection } from 'firebase/firestore'</pre></td>
91+
</tr>
92+
<tr>
93+
<td>doc</td>
94+
<td><code>import { doc } from 'firebase/firestore'</code></td>
95+
</tr>
96+
<tr>
97+
<td>collectionGroup</td>
98+
<td><code>import { doc } from 'firebase/firestore'</code></td>
99+
</tr>
100+
</tbody>
101+
</table>
102+
103+
### Code splitting and lazy-loading
104+
105+
AngularFire does not lazy-load services any longer. We have provided a helper observable for detecting when a new service instance is instantiated. In this example we'll code split out of all the Firestore related code and lazy-load
106+
107+
```ts
108+
// firestore_operations.ts
109+
import { collection, getFirestore } from 'firebase/firestore';
110+
import { collectionData, firestoreInstance$ } from '@angular/fire/firestore';
111+
import { first } from 'rxjs/operators';
112+
113+
export { getFirestore };
114+
115+
export const fooData = firestoreInstance$.pipe(
116+
first(),
117+
concatMap(firestore => collectionData<IFoo>(collection(firestore, 'foo'))),
118+
);
119+
```
120+
121+
```ts
122+
export class AuthService {
123+
constructor() {
124+
getRedirectResult().then(result => {
125+
// Initialize Firestore only after a user logs in
126+
if (result.user) {
127+
const { getFirestore } = await import('./firestore_operations');
128+
getFirestore();
129+
}
130+
});
131+
}
132+
}
133+
```
134+
135+
```ts
136+
@Component({})
137+
export class Foo {
138+
data: Observable<IFoo[]>;
139+
constructor() {
140+
this.data = of(undefined).pipe(
141+
concatMap(() => import('./firestore_operations')),
142+
concatMap(it => it.fooData)
143+
);
144+
}
145+
}
146+
```
147+
148+
### Working with multiple apps / instances
149+
150+
In AngularFire v7 working with multiple instances was difficult, in the new SDK we have new DI tokens that make working with them much more straight forward.
151+
152+
```ts
153+
@NgModule({
154+
imports: [
155+
provideFirebaseApp(() => initializeApp(config)),
156+
provideFirebaseApp(() => initializeApp(config2, 'anotherApp')),
157+
provideStorage(() => getStorage(getApp())),
158+
provideStorage(() => getStorage(getApp(), 'another bucket')),
159+
provideStorage(() => getStorage(getApp('anotherApp'))),
160+
],
161+
providers: [
162+
{ provide: FIRESTORE_SETTINGS, useValue: { ignoreUndefinedProperties: true } },
163+
],
164+
})
165+
```
166+
167+
```ts
168+
import { FirebaseApp, FirebaseApps } from '@angular/fire/app';
169+
import { Storage, StorageIsntances } from '@angular/fire/storage';
170+
171+
export class Foo {
172+
constructor(
173+
defaultApp: FirebaseApp, // Injects the default FirebaseApp
174+
firebaseApps: FirebaseApps, // Injects an array of all initialized Firebase Apps
175+
storage: Storage, // Injects the default FirebaseApp's default storage instance
176+
storageInstances: StorageInstances, // Injects an array of all the intialized storage instances
177+
) { }
178+
}
179+
```
180+
How the main injection tokens (i.e, `FirebaseApp`, `Storage`) function have changed from v7 but it should provide a much more powerful and intuitive API.

sample/src/app/app.component.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ export class AppComponent {
4040
public auth: Auth, // default Firbase Auth
4141
public apps: FirebaseApps, // all initialized App instances
4242
public authInstances: AuthInstances, // all initialized Auth instances
43-
public firestore: Firestore,
44-
public firestoreInstances: FirestoreInstances,
43+
@Optional() public firestore: Firestore,
44+
@Optional() public firestoreInstances: FirestoreInstances,
4545
appRef: ApplicationRef,
4646
zone: NgZone,
4747
) {
@@ -50,7 +50,7 @@ export class AppComponent {
5050
// onAuthStateChanged(auth, it => console.log('onAuthStateChanged', it));
5151
authState(auth).subscribe(it => console.log('authState', it));
5252
appRef.isStable.pipe(debounceTime(200)).subscribe(it => console.log('isStable', it));
53-
console.log((app as any).container.providers);
53+
console.log((app as any).container.providers.keys());
5454
firestoreInstance$.subscribe(it => console.log('$', it));
5555
initializeFirestore$.subscribe(it => console.log('init', it));
5656
}

0 commit comments

Comments
 (0)