|
| 1 | +# Actualizando a AngularFire 7.0 |
| 2 | + |
| 3 | +Diseñado para ejecutarse con Angular 12, AngularFire 7.0 le permite aprovechar al máximo el nuevo Firebase JS SDK (v9) tree-shakable, al mismo tiempo, proporciona una experiencia compatible con la API anterior. |
| 4 | + |
| 5 | +`ng update @angular/fire` |
| 6 | + |
| 7 | +## Breaking changes |
| 8 | + |
| 9 | +* Angular 12 es requerido |
| 10 | +* AngularFire ahora solo funciona en aplicaciones con Ivy. |
| 11 | +* Firebase JS SDK v9 es requerido |
| 12 | +* La API AngularFire v6 existente se ha movido de `@angular/fire/*` a `@angular/fire/compat/*` (ver modo de compatibilidad) |
| 13 | +* **compat/auth:** El token `USE_EMULATOR` para DI ahora esta en el formulario de `['http://localhost:9099']` |
| 14 | + |
| 15 | +## Modo de compatibilidad |
| 16 | + |
| 17 | +AngularFire v7.0 tiene una capa de compatibilidad que admite la API de AngularFire v6.0. Simplemente cambie sus imports de `@angular/fire/*` a `@angular/fire/compat/*` y `firebase/*` a `firebase/compat/*`. |
| 18 | + |
| 19 | +Si bien no es tan variable como el nuevo SDK modular, esto le permite actualizar y aprovechar los beneficios del nuevo SDK lo antes posible. |
| 20 | + |
| 21 | +**La mayoría de los desarrolladores pueden detenerse aquí por ahora, ya que la nueva API no está completa.** |
| 22 | + |
| 23 | +## **NUEVO** SDK Modular |
| 24 | + |
| 25 | +### Inicialización |
| 26 | + |
| 27 | +Para admitir mejor la capacidad tree-shakability introducida en Firebase v9 y reducir el mantenimiento requerido cuando el SDK de JS agrega nuevos indicadores de configuración, los "providers" de AngularFire ahora toman una "factory" para una instancia completa del SDK que le gustaría inyectar. |
| 28 | + |
| 29 | +**Antes:** |
| 30 | +```ts |
| 31 | +@NgModule({ |
| 32 | + imports: [ |
| 33 | + AngularFireModule.initializeApp(config), |
| 34 | + AngularFirestoreModule.enablePersistence(), |
| 35 | + AngularFireStorageModule, |
| 36 | + ], |
| 37 | + providers: [ |
| 38 | + { provide: USE_EMULATOR, useValue: ['localhost', 8080] }, |
| 39 | + ], |
| 40 | +}) |
| 41 | +``` |
| 42 | + |
| 43 | +**SDK Modular:** |
| 44 | +```ts |
| 45 | +@NgModule({ |
| 46 | + imports: [ |
| 47 | + provideFirebaseApp(() => initializeApp(config)), |
| 48 | + provideFirestore(() => { |
| 49 | + const firestore = getFirestore(); |
| 50 | + connectFirestoreEmulator(firestore, 'localhost', 8080); |
| 51 | + enableIndexedDbPersistence(firestore); |
| 52 | + return firestore; |
| 53 | + }), |
| 54 | + provideStorage(() => getStorage()), |
| 55 | + ], |
| 56 | +}) |
| 57 | +``` |
| 58 | + |
| 59 | +### Inyectando servicios |
| 60 | + |
| 61 | +Antes, cuando inyectaba los servicios SDK de Firebase JS en AngularFire, se cargaban de forma diferida y se le devolvía un "promise-proxy. En AngularFire v7 obtienes el servicio iniciado directamente. Ya no cargamos de manera "lazy" por ti. |
| 62 | + |
| 63 | +```ts |
| 64 | +import { Firestore, doc, onSnapshot, DocumentReference, docSnapshots } from '@angular/fire/firestore'; |
| 65 | + |
| 66 | +@Component({}) |
| 67 | +export class Foo { |
| 68 | + doc: DocumentReference; |
| 69 | + constructor( |
| 70 | + firestore: Firestore, // Injects the instantiated Firestore instance |
| 71 | + ) { |
| 72 | + // You can directly operate on the instance with JS SDK methods which we've |
| 73 | + // reexported in AngularFire |
| 74 | + this.doc = doc(firestore, 'foo/1'); |
| 75 | + onSnapshot(doc, snap => { |
| 76 | + // ... |
| 77 | + }); |
| 78 | + // or use the convenience observables |
| 79 | + docSnapshots(doc).subscribe(...); |
| 80 | + } |
| 81 | + async update() { |
| 82 | + await updateDoc(this.doc, { ... }); |
| 83 | + ... |
| 84 | + } |
| 85 | +} |
| 86 | +``` |
| 87 | + |
| 88 | +### Trabajando con multiple apps / instances |
| 89 | + |
| 90 | +En AngularFire v7, trabajar con múltiples instancias fue difícil, en el nuevo SDK tenemos nuevos tokens DI que hacen que trabajar con ellos sea mucho más sencillo. |
| 91 | + |
| 92 | +```ts |
| 93 | +@NgModule({ |
| 94 | + imports: [ |
| 95 | + provideFirebaseApp(() => initializeApp(config)), |
| 96 | + provideFirebaseApp(() => initializeApp(config2, 'anotherApp')), |
| 97 | + provideStorage(() => getStorage()), |
| 98 | + provideStorage(() => getStorage(getApp(), 'anotherBucket')), |
| 99 | + provideStorage(() => getStorage(getApp('anotherApp'))), |
| 100 | + ], |
| 101 | +}) |
| 102 | +``` |
| 103 | + |
| 104 | +```ts |
| 105 | +import { FirebaseApp, FirebaseApps } from '@angular/fire/app'; |
| 106 | +import { Storage, StorageInstances } from '@angular/fire/storage'; |
| 107 | + |
| 108 | +export class Foo { |
| 109 | + constructor( |
| 110 | + defaultApp: FirebaseApp, // Injects the default FirebaseApp |
| 111 | + allFirebaseApps: FirebaseApps, // Injects an array of all initialized Firebase Apps |
| 112 | + storage: Storage, // Injects the default storage instance |
| 113 | + allStorageInstances: StorageInstances, // Injects an array of all the intialized storage instances |
| 114 | + ) { } |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +Cómo han cambiado las funciones de los principales tokens de inyección (es decir, `FirebaseApp`, `Storage`) desde v7, pero debería proporcionar una API mucho más poderosa e intuitiva. |
| 119 | + |
| 120 | +### API |
| 121 | + |
| 122 | +Más allá de la inyección de dependencia AngularFire presenta una API completamente nueva: |
| 123 | + |
| 124 | +1) Ya no manejamos la carga diferida de los módulos SDK de Firebase JS por usted |
| 125 | +1) Ya no brindamos clases más allá de la inyección de dependencia |
| 126 | +1) No más Proxy / Promise-Proxy |
| 127 | +1) Reexportamos y empaquetamos en zonas todas las API de Firebase y RxFire |
| 128 | + |
| 129 | +Por lo tanto, desarrollar con el nuevo AngularFire es fácil, puede usarlo como el SDK estándar de Firebase JS. Simplemente cambie todas sus importaciones de `firebase/app` a `@angular/fire/app`, `firebase/firestore` a `@angular/fire/firestore`, `firebase/database` a `@angular/fire/database`, etc. Entonces, si se siente cómodo con RXJS y le gustaría usar algunos de nuestros operadores de conveniencia, puede sumergirse en esa caja de herramientas. |
| 130 | + |
| 131 | +#### Alternatives to v6 APIs |
| 132 | + |
| 133 | +<table> |
| 134 | + <thead> |
| 135 | + <tr> |
| 136 | + <th colspan="2">v6 / Compat</th> |
| 137 | + <th>v7 Modular</th> |
| 138 | + </tr> |
| 139 | + </thead> |
| 140 | + <tbody> |
| 141 | + <tr> |
| 142 | + <th rowspan="3">AngularFirestore</th> |
| 143 | + <td>doc</td> |
| 144 | + <td> |
| 145 | + |
| 146 | +```ts |
| 147 | +import { doc } from '@angular/fire/firestore'; |
| 148 | +doc<T>(firestore, 'foo/bar') // DocumentReference<T> |
| 149 | +``` |
| 150 | +</td> |
| 151 | + </tr> |
| 152 | + <tr> |
| 153 | + <td>collection</td> |
| 154 | + <td> |
| 155 | + |
| 156 | +```ts |
| 157 | +import { collection } from '@angular/fire/firestore'; |
| 158 | +collection<T>(firestore, 'foo') // CollectionReference<T> |
| 159 | +``` |
| 160 | +</td> |
| 161 | + </tr> |
| 162 | + <tr> |
| 163 | + <td>collectionGroup</td> |
| 164 | + <td> |
| 165 | + |
| 166 | +```ts |
| 167 | +import { collectionGroup } from '@angular/fire/firestore'; |
| 168 | +collectionGroup<T>(firestore, 'foo') // Query<T> |
| 169 | +``` |
| 170 | +</td> |
| 171 | + </tr> |
| 172 | + <tr> |
| 173 | + <th rowspan="7">AngularFirestoreDocument</th> |
| 174 | + <td>set</td> |
| 175 | + <td> |
| 176 | + |
| 177 | +```ts |
| 178 | +import { setDoc } from '@angular/fire/firestore'; |
| 179 | +setDoc(docRef, { ... }) // Promise<void> |
| 180 | +``` |
| 181 | +</td> |
| 182 | + |
| 183 | +</td> |
| 184 | + </tr> |
| 185 | + <tr> |
| 186 | + <td>update</td> |
| 187 | + <td> |
| 188 | + |
| 189 | +```ts |
| 190 | +import { updateDoc } from '@angular/fire/firestore'; |
| 191 | +updateDoc(docRef, { ... }) // Promise<void> |
| 192 | +``` |
| 193 | +</td> |
| 194 | + </tr> |
| 195 | + <tr> |
| 196 | + <td>delete</td> |
| 197 | + <td> |
| 198 | + |
| 199 | +```ts |
| 200 | +import { deleteDoc } from '@angular/fire/firestore'; |
| 201 | +deleteDoc(docRef) // Promise<void> |
| 202 | +``` |
| 203 | +</td> |
| 204 | + </tr> |
| 205 | + <tr> |
| 206 | + <td>collection</td> |
| 207 | + <td> |
| 208 | + |
| 209 | +```ts |
| 210 | +import { collection } from '@angular/fire/firestore'; |
| 211 | +collection<T>(docRef, 'bar') // CollectionReference<T> |
| 212 | +``` |
| 213 | +</td> |
| 214 | + </tr> |
| 215 | + <tr> |
| 216 | + <td>snapshotChanges</td> |
| 217 | + <td> |
| 218 | + |
| 219 | +```ts |
| 220 | +import { docSnapshots } from '@angular/fire/firestore'; |
| 221 | +docSnapshots<T>(docRef) // Observable<DocumentSnapshot<T>> |
| 222 | +``` |
| 223 | +</td> |
| 224 | + |
| 225 | +</td> |
| 226 | + </tr> |
| 227 | + <tr> |
| 228 | + <td>valueChanges</td> |
| 229 | + <td> |
| 230 | + |
| 231 | +```ts |
| 232 | +import { docData } from '@angular/fire/firestore'; |
| 233 | +docData<T>(docRef) // Observable<T> |
| 234 | +``` |
| 235 | +</td> |
| 236 | + </tr> |
| 237 | + <tr> |
| 238 | + <td>get</td> |
| 239 | + <td> |
| 240 | + |
| 241 | +```ts |
| 242 | +import { getDoc } from '@angular/fire/firestore'; |
| 243 | +getDoc<T>(docRef) // Promise<DocumentSnapshot<T>> |
| 244 | +``` |
| 245 | + |
| 246 | +</td> |
| 247 | + </tr> |
| 248 | + </tbody> |
| 249 | +</table> |
| 250 | + |
| 251 | +### "Code splitting " y "lazy-loading" |
| 252 | + |
| 253 | +AngularFire ya no realiza la carga diferida de los servicios. Hemos proporcionado un asistente observable para detectar cuándo se crea una nueva instancia de servicio. En este ejemplo, dividiremos el código de todo el código relacionado con Firestore y la carga diferida |
| 254 | + |
| 255 | +```ts |
| 256 | +// firestore_operations.ts |
| 257 | +import { |
| 258 | + collectionData, |
| 259 | + firestoreInstance$, |
| 260 | + collection, |
| 261 | + getFirestore |
| 262 | +} from '@angular/fire/firestore'; |
| 263 | +import { first } from 'rxjs/operators'; |
| 264 | +import { IFoo } from '../interfaces'; |
| 265 | + |
| 266 | +export { getFirestore }; |
| 267 | + |
| 268 | +export const fooData = firestoreInstance$.pipe( |
| 269 | + first(), |
| 270 | + concatMap(firestore => collectionData<IFoo>(collection(firestore, 'foo'))), |
| 271 | +); |
| 272 | +``` |
| 273 | + |
| 274 | +```ts |
| 275 | +export class AuthService { |
| 276 | + constructor() { |
| 277 | + getRedirectResult().then(result => { |
| 278 | + // Initialize Firestore only after a user logs in |
| 279 | + if (result.user) { |
| 280 | + const { getFirestore } = await import('./firestore_operations'); |
| 281 | + getFirestore(); |
| 282 | + } |
| 283 | + }); |
| 284 | + } |
| 285 | +} |
| 286 | +``` |
| 287 | + |
| 288 | +```ts |
| 289 | +@Component({}) |
| 290 | +export class Foo { |
| 291 | + data: Observable<IFoo[]>; |
| 292 | + constructor() { |
| 293 | + this.data = of(undefined).pipe( |
| 294 | + concatMap(() => import('./firestore_operations')), |
| 295 | + concatMap(it => it.fooData) |
| 296 | + ); |
| 297 | + } |
| 298 | +} |
| 299 | +``` |
0 commit comments