Skip to content

Instantly share code, notes, and snippets.

View alxhub's full-sized avatar

Alex Rickabaugh alxhub

  • Google, Inc.
  • San Francisco, CA
View GitHub Profile

Problem

Developing Ivy requires being able to compile the same framework code, examples, tests, etc. using the legacy pipeline (ngc, view engine, etc) and using one of several new Ivy pipelines. Eventually, too, we want to start testing Ivy in g3, via a multi-phase rollout.

Development Requirements

We have several different kinds of code, both in the Angular repository and in others (e.g. CLI). In developing Ivy, we need to be able to test this code against the new compiler(s) and runtime, while continuing to support development of the existing Angular.

Types of code include:

@Injectable
export class OnDestroySvc {
private _other: OnDestroy[] = [];
register(other: OnDestroy) {
this._other.push(other);
}
ngOnDestroy(): void {
function runInZone<T>(zone: Zone): (obs: Observable<T>) => Observable<T> {
return (obs: Observable<T>) => {
return new Observable<any>(observer => {
const sub = obs.subscribe(
value => zone.run(() => observer.next(value)),
err => zone.run(() => observer.error(err)),
() => zone.run(() => observer.complete()),
);
return () => sub.unsubscribe();
});
@Injectable({
providedIn: 'root',
useClass: ServiceClientImpl,
})
class AbstractService {
static ngInjectableDef = {
factory: () => new ServiceClientImpl(inject(Dep)),
providedIn: 'root',
};
}
import {LibModule} from 'lib';
@Component({
template: '<component-from-sublib></component-from-sublib>',
})
export class AppComponent {
// Ivy generated:
static ngComponentDef = defineComponent({
components: [
@Injectable()
export class OnDestroyService implements OnDestroy {
onDestroy = new Set<OnDestroy>();
register(service: OnDestroy) {
this.onDestroy.add(service);
}
ngOnDestroy(): void {
this.onDestroy.forEach(svc => svc.ngOnDestroy());

What is the forRoot() method?

The forRoot() static method is a convention that makes it easy for developers to configure services and providers for a module which are intended to be singletons. For services it is preferable to specify providedIn: 'root' on the service's @Injectable(), which has the same effect.

... (rest)

Should I add application-wide providers to the root AppModule or the root AppComponent?

Application-wide providers should be defined by specifying providedIn: 'root' on their @Injectable() decorator (in the case of services) or at InjectionToken construction (in the case of tokens being provided). Providers created this way will automatically be made available to the entire application and don't need to be listed in any module.

//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
@alxhub
alxhub / tree-shakeable-providers.ts
Created March 16, 2018 19:04
Tree-shakeable providers Example
// Here's a fictitious LayoutService without a module!
//
// It'll automatically be available in the application's
// root injector (as if it was provided in the AppModule).
//
// Even though it's in the root injector, if this service
// is only used in a lazy loaded context, it will be lazy
// loaded!
@Injectable({
@alxhub
alxhub / onUnsubscribe.ts
Created March 16, 2018 15:42
onUnsubscribe Rx operator
function onUnsubscribe<T>(fn: () => void): (obs: Observable<T>) => Observable<T> {
return (obs: Observable<T>): Observable<T> => {
return new Observable<T>(subscriber => {
const sub = obs.subscribe(subscriber);
return () => {
sub.unsubscribe();
fn();
};
});
};