Skip to content

AngularFire 6.0 🔥 #2376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,9 @@
The official [Angular](https://angular.io/) library for [Firebase](https://firebase.google.com/).

```bash
ng add @angular/fire@next
ng add @angular/fire
```

---

> **WARNING**: Master branch is the work in progress for version 6 of AngularFire. [You can find version 5 here](https://github.com/angular/angularfire/tree/v5), if you're looking for documentation or to contribute to stable. [Learn more about the road toward version 6 here](https://github.com/angular/angularfire/issues/2267).

---

## What is AngularFire?

- **Observable based** - Use the power of RxJS, Angular, and Firebase.
Expand Down
111 changes: 33 additions & 78 deletions docs/performance/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Understand your Angular application's real-world performance with [Firebase Perf

```ts
import { AngularFireModule } from '@angular/fire';
import { AngularFirePerformanceModule } from '@angular/fire/performance';
import { AngularFirePerformanceModule, PerformanceMonitoringService } from '@angular/fire/performance';
import { environment } from '../environments/environment';

@NgModule({
Expand All @@ -16,6 +16,9 @@ import { environment } from '../environments/environment';
AngularFirePerformanceModule,
...
],
providers: [
PerformanceMonitoringService
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
Expand All @@ -30,7 +33,7 @@ The page load trace breaks down into the following default metrics:
* [domContentLoadedEventEnd traces](https://firebase.google.com/docs/perf-mon/automatic-web#domContentLoaded) — measure the time between when the user navigates to a page and when the initial HTML document is completely loaded and parsed
* [loadEventEnd traces](https://firebase.google.com/docs/perf-mon/automatic-web#loadEventEnd) — measure the time between when the user navigates to the page and when the current document's load event completes
* [first input delay traces](https://firebase.google.com/docs/perf-mon/automatic-web#input-delay) — measure the time between when the user interacts with a page and when the browser is able to respond to that input
* **Angular specific traces** - measure the time needed for `ApplicationRef.isStable` to be true, an important metric to track if you're concerned about solving Zone.js issues for proper functionality of NGSW and Server Side Rendering
* **Angular specific traces** - `PerformanceMonitoringService` will measure the time needed for `ApplicationRef.isStable` to be true, an important metric to track if you're concerned about solving Zone.js issues for proper functionality of NGSW and Server Side Rendering

### Measuring First Input Delay

Expand All @@ -44,24 +47,43 @@ Then add `import 'first-input-delay';` to your `src/polyfills.ts`.

## Manual traces

You can inject `AngularFirePerformance` to perform manual traces on Observables.
You can inject `AngularFirePerformance` to perform manual traces.

```ts
constructor(private performance: AngularFirePerformance) {}

ngOnInit() {
const trace = this.performance.trace('some-trace');
trace.start();
...
trace.stop();
}
```

## RXJS operators

AngularFire provides a number of RXJS operaters which wrap the User Timing API. These are picked up by performance monitoring tools such as Chrome Inspector and Firebase Performance Monitoring.

```ts
constructor(private afp: AngularFirePerformance, private afs: AngularFirestore) {}
import { trace } from '@angular/fire/performance';

...

constructor(private performance: AngularFirePerformance, private afs: AngularFirestore) {}

ngOnInit() {
this.articles = afs.collection('articles')
.collection('articles', ref => ref.orderBy('publishedAt', 'desc'))
.snapshotChanges()
.pipe(
// measure the amount of time between the Observable being subscribed to and first emission (or completion)
this.afp.trace('getArticles'),
trace('getArticles'),
map(articles => ...)
);
}
```

### `trace(name: string, options?: TraceOptions)`
### `trace(name: string)`

The most basic operator, `trace` will measure the amount of time it takes for your observable to either complete or emit its first value. Beyond the basic trace there are several other operators:

Expand All @@ -70,7 +92,7 @@ The most basic operator, `trace` will measure the amount of time it takes for yo
traceUntil(
name: string,
test: (T) => Boolean,
options?: TraceOptions & { orComplete?: true }
options?: { orComplete?: true }
)
</pre>
</h3>
Expand All @@ -84,7 +106,7 @@ If the `orComplete` option is passed it will complete the trace when the observa
traceWhile(
name: string,
test: (T) => Boolean,
options?: TraceOptions & { orComplete?: true }
options?: { orComplete?: true }
)
</pre>
</h3>
Expand All @@ -93,83 +115,16 @@ Starting with an emission that passes the provided test, trace until an emission

If the `orComplete` option is passed it will complete any existing trace when the observable completes.

### `traceUntilLast(name: string, options?: TraceOptions)`
### `traceUntilLast(name: string)`

Trace the observable until completion.

### `traceUntilFirst(name: string, options?: TraceOptions)`
### `traceUntilFirst(name: string)`

Traces the observable until the first emission.

## Advanced usage

### Configuration via Dependency Injection

By default, `AngularFirePerformanceModule` traces your Angular application's time to `ApplicationRef.isStable`. `isStable` is an important metric to track if you're concerned about proper functionality of NGSW and Server Side Rendering. If you want to opt-out of the tracing of this metric use the `AUTOMATICALLY_TRACE_CORE_NG_METRICS` injection token:

```ts
import { NgModule } from '@angular/core';
import { AngularFirePerformanceModule, AUTOMATICALLY_TRACE_CORE_NG_METRICS } from '@angular/fire/functions';

@NgModule({
imports: [
...
AngularFirePerformanceModule,
...
],
...
providers: [
{ provide: AUTOMATICALLY_TRACE_CORE_NG_METRICS, useValue: false }
]
})
export class AppModule {}
```

Similarly, setting `INSTRUMENTATION_ENABLED` or `DATA_COLLECTION_ENABLED` to false disable all automatic and custom traces respectively.

### Get at an observable form of trace

`trace$(name:string)` provides an observable version of `firebase/perf`'s `.trace` method; the basis for `AngularFirePerfomance`'s pipes.

`.subscribe()` is equivalent to calling `.start()`
`.unsubscribe()` is equivalent to calling `.stop()`

### Using `TraceOptions` to collect additional metrics

`TraceOptions` can be provided to the aformentioned operators to collect custom metrics and attributes on your traces:

```ts
type TraceOptions = {
metrics?: { [key:string]: number },
attributes?: { [key:string]: string },
attribute$?: { [key:string]: Observable<string> },
incrementMetric$: { [key:string]: Observable<number|void|null|undefined> },
metric$?: { [key:string]: Observable<number> }
};
```

#### Usage:

```ts
const articleLength$ = this.articles.pipe(
map(actions => actions.length)
);

const articleSize$ = this.articles.pipe(
map(actions => actions.reduce((sum, a) => sum += JSON.stringify(a.payload.doc.data()).length))
)

this.articles = afs.collection('articles')
.collection('articles', ref => ref.orderBy('publishedAt', 'desc'))
.snapshotChanges()
.pipe(
this.afp.trace('getArticles', {
attributes: { gitSha: '1d277f823ad98dd739fb86e9a6c440aa8237ff3a' },
metrics: { something: 42 },
metrics$: { count: articleLength$, size: articleSize$ },
attributes$: { user: this.afAuth.user },
incrementMetric$: { buttonClicks: fromEvent(button, 'click') }
}),
share()
);
```
Set `INSTRUMENTATION_ENABLED` or `DATA_COLLECTION_ENABLED` to false disable all automatic and custom traces respectively.
9 changes: 3 additions & 6 deletions docs/version-6-upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@

Intended to be run with Angular 9; version 6 of AngularFire drops support for Angular version 8 and below, older versions of typescript, Firebase, drops `firebase-node`, `database-deprecated`, and more.

> **WARNING**: Version 6 is still a Release Candidate and subject to change, [please monitor the changelog for up-to-date information on what we've been up to](../CHANGELOG.md).

We're aiming to release 6.0 with an upgrade schematic to automate most of the required changes, however as of RC.1 that script is not yet available.

## Breaking changes:

* Support for Angular versions less than 9 has been dropped
* Support for Firebase JS SDK versions less than 7.8 has been dropped
* Support for `firebase-tools` less than 7.12 has been dropped
* Support for Firebase JS SDK versions less than 7.13.1 has been dropped
* Support for `firebase-tools` less than 8.0 has been dropped
* The `angularfire2` NPM library will no longer be updated
* Dropped `@angular/fire/firebase-node` and `@angular/fire/database-depreciated`
* We make use of Proxy in more modules, you'll need to polyfill if you want to support IE 11
* We've standardized our DI Token naming conventions across all modules
* `AngularFireAuth` has dropped the `auth` property and instead Promise Proxies the underlying Firebase `auth.Auth` instance; allowing your development experience to more closely mirror the JS SDK. Similar changes have been made to `AngularFireFunctions`, `AngularFireMessaging`, and `AngularFirePerformance`.
* `AngularFireAuthGuard` and `canActivate` have dropped support for raw pipes, this was never working correctly in AOT
* `AngularFirePerformance` has been simplified, the RXJS pipes are now exported as pure-functions outside the class. Automatic tracking of `isStable` timing has now been moved into `PerformanceMonitoringService` and we've dropped the `AUTOMATICALLY_TRACE_CORE_NG_METRICS` DI token.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@
"@angular/platform-browser": "^9.0.0",
"@angular/platform-browser-dynamic": "^9.0.0",
"@angular/router": "^9.0.0",
"firebase": "^7.8.0",
"firebase-admin": "^8.9.2",
"firebase-functions": "^3.3.0",
"firebase-tools": "^7.12.1",
"firebase": "^7.13.1",
"firebase-admin": "^8.10.0",
"firebase-functions": "^3.6.0",
"firebase-tools": "^8.0.0",
"fs-extra": "^8.0.1",
"fuzzy": "^0.1.3",
"inquirer": "^6.2.2",
Expand Down
9 changes: 6 additions & 3 deletions sample/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@
"outputPath": "dist/sample/server",
"main": "server.ts",
"tsConfig": "tsconfig.server.json",
"bundleDependencies": false,
"externalDependencies": [
"@firebase/firestore",
"@firebase/firestore"
],
"verbose": true
]
},
"configurations": {
"production": {
Expand Down Expand Up @@ -171,7 +172,9 @@
},
"deploy": {
"builder": "@angular/fire:deploy",
"options": {}
"options": {
"ssr": true
}
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions sample/firebase.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"hosting": [
{
"target": "sample",
"public": "dist/sample/browser",
"public": "dist/sample/dist/sample/browser",
"ignore": [
"firebase.json",
"**/.*",
Expand All @@ -11,9 +11,12 @@
"rewrites": [
{
"source": "**",
"destination": "/index.html"
"function": "ssr"
}
]
}
]
],
"functions": {
"source": "dist/sample"
}
}
41 changes: 22 additions & 19 deletions sample/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,39 @@
},
"private": true,
"dependencies": {
"@angular/animations": "~9.0.5",
"@angular/common": "~9.0.5",
"@angular/compiler": "~9.0.5",
"@angular/core": "~9.0.5",
"@angular/animations": "~9.1.0",
"@angular/common": "~9.1.0",
"@angular/compiler": "~9.1.0",
"@angular/core": "~9.1.0",
"@angular/fire": "file:../dist/packages-dist",
"@angular/forms": "~9.0.5",
"@angular/platform-browser": "~9.0.5",
"@angular/platform-browser-dynamic": "~9.0.5",
"@angular/platform-server": "^9.0.5",
"@angular/router": "~9.0.5",
"@angular/service-worker": "^9.0.5",
"@nguniversal/express-engine": "^9.0.1",
"firebase": "^7.8.0",
"@angular/forms": "~9.1.0",
"@angular/platform-browser": "~9.1.0",
"@angular/platform-browser-dynamic": "~9.1.0",
"@angular/platform-server": "~9.1.0",
"@angular/router": "~9.1.0",
"@angular/service-worker": "~9.1.0",
"@nguniversal/express-engine": "~9.1.0",
"firebase": "^7.13.1",
"rxjs": "~6.5.4",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/architect": "~0.900.0",
"@angular-devkit/build-angular": "~0.900.5",
"@angular/cli": "~9.0.5",
"@angular/compiler-cli": "~9.0.5",
"@angular/language-service": "~9.0.5",
"@nguniversal/builders": "^9.0.1",
"@angular-devkit/architect": "~0.901.0",
"@angular-devkit/build-angular": "~0.901.0",
"@angular/cli": "~9.1.0",
"@angular/compiler-cli": "~9.1.0",
"@angular/language-service": "~9.1.0",
"@nguniversal/builders": "^9.1.0",
"@types/jasmine": "~3.5.0",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^5.1.2",
"express-serve-static-core": "^0.1.1",
"firebase-tools": "^7.12.1",
"firebase-admin": "^8.10.0",
"firebase-functions": "^3.6.0",
"firebase-functions-test": "^0.2.0",
"firebase-tools": "^8.0.0",
"fuzzy": "^0.1.3",
"inquirer": "^6.2.2",
"inquirer-autocomplete-prompt": "^1.0.1",
Expand Down
3 changes: 2 additions & 1 deletion sample/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { AngularFirestoreModule, SETTINGS as FIRESTORE_SETTINGS } from '@angular
import { AngularFireMessagingModule } from '@angular/fire/messaging';
import { AngularFireFunctionsModule, ORIGIN as FUNCTIONS_ORIGIN } from '@angular/fire/functions';
import { AngularFireRemoteConfigModule, SETTINGS as REMOTE_CONFIG_SETTINGS } from '@angular/fire/remote-config';
import { AngularFirePerformanceModule } from '@angular/fire/performance';
import { AngularFirePerformanceModule, PerformanceMonitoringService } from '@angular/fire/performance';
import { AngularFireAuthGuardModule } from '@angular/fire/auth-guard';
import { DatabaseComponent } from './database/database.component';
import { StorageComponent } from './storage/storage.component';
Expand Down Expand Up @@ -49,6 +49,7 @@ const shouldUseEmulator = () => false;
providers: [
UserTrackingService,
ScreenTrackingService,
PerformanceMonitoringService,
{ provide: ANALYTICS_DEBUG_MODE, useFactory: () => isDevMode() },
{ provide: DATABASE_URL, useFactory: () => shouldUseEmulator() ? `http://localhost:9000?ns=${environment.firebase.projectId}` : undefined },
{ provide: FIRESTORE_SETTINGS, useFactory: () => shouldUseEmulator() ? { host: 'localhost:8080', ssl: false } : {} },
Expand Down
6 changes: 5 additions & 1 deletion sample/src/app/database/database.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AngularFireDatabase } from '@angular/fire/database';
import { Observable } from 'rxjs';
import { TransferState, makeStateKey } from '@angular/platform-browser';
import { startWith, tap } from 'rxjs/operators';
import { trace } from '@angular/fire/performance';

@Component({
selector: 'app-database',
Expand All @@ -22,7 +23,10 @@ export class DatabaseComponent implements OnInit {
const doc = database.object('test');
const key = makeStateKey(doc.query.toString());
const existing = state.get(key, undefined);
this.testObjectValue$ = doc.valueChanges().pipe(existing ? startWith(existing) : tap(it => state.set(key, it)));
this.testObjectValue$ = doc.valueChanges().pipe(
trace('database'),
existing ? startWith(existing) : tap(it => state.set(key, it))
);
}

ngOnInit(): void {
Expand Down
Loading