Skip to content

Commit aa980b1

Browse files
committed
angular: use ES/ivy way to lazy-load the "_db-view" module (debt)
1 parent ca5186f commit aa980b1

File tree

5 files changed

+44
-52
lines changed

5 files changed

+44
-52
lines changed

src/web/browser-window/app/_accounts/account.component.ts

+19-21
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ export class AccountComponent extends NgChangesObservableComponent implements On
8080
@ViewChild("tplDbViewComponentContainerRef", {read: ViewContainerRef, static: true})
8181
private readonly tplDbViewComponentContainerRef!: ViewContainerRef;
8282

83-
private tplDbViewComponentRef: Unpacked<ReturnType<typeof DbViewModuleResolve.prototype.buildComponentRef>> | undefined;
84-
8583
private readonly databaseViewToggled$ = this.account$.pipe(
8684
map((account) => ({
8785
login: account.accountConfig.login,
@@ -187,20 +185,25 @@ export class AccountComponent extends NgChangesObservableComponent implements On
187185
);
188186

189187
this.subscription.add(
190-
this.databaseViewToggled$.subscribe(async ([{login, databaseView}]) => {
191-
this.viewModeClass = databaseView
192-
? "vm-database"
193-
: "vm-live";
194-
195-
if (!databaseView) {
196-
this.focusPrimaryWebView();
197-
} else if (!this.tplDbViewComponentRef) {
198-
// lazy-load the local database view component ("local store" feature)
199-
this.tplDbViewComponentRef = await this.dbViewModuleResolve.buildComponentRef({login});
200-
this.tplDbViewComponentContainerRef.insert(this.tplDbViewComponentRef.hostView);
201-
this.tplDbViewComponentRef.changeDetectorRef.detectChanges();
202-
}
203-
}),
188+
(() => {
189+
let dbViewEntryComponentMounted = false;
190+
191+
return this.databaseViewToggled$.subscribe(async ([{login, databaseView}]) => {
192+
this.viewModeClass = databaseView
193+
? "vm-database"
194+
: "vm-live";
195+
196+
if (!databaseView) {
197+
this.focusPrimaryWebView();
198+
} else if (!dbViewEntryComponentMounted) {
199+
await this.dbViewModuleResolve.mountDbViewEntryComponent(
200+
this.tplDbViewComponentContainerRef,
201+
{login},
202+
);
203+
dbViewEntryComponentMounted = true;
204+
}
205+
});
206+
})(),
204207
);
205208

206209
this.subscription.add(
@@ -353,11 +356,6 @@ export class AccountComponent extends NgChangesObservableComponent implements On
353356
super.ngOnDestroy();
354357
this.logger.info(`ngOnDestroy()`);
355358
this.subscription.unsubscribe();
356-
if (this.tplDbViewComponentRef) {
357-
// TODO angular: there is probably no need to trigger this "destroy" explicitly
358-
// debug the db-view component to verify that
359-
this.tplDbViewComponentRef.destroy();
360-
}
361359
}
362360

363361
private focusPrimaryWebView() {

src/web/browser-window/app/_accounts/db-view-module-resolve.service.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
import {ComponentFactory, ComponentRef, Injectable, Injector, NgModuleFactoryLoader} from "@angular/core";
1+
import {Compiler, ComponentFactory, ComponentRef, Injectable, Injector, ViewContainerRef} from "@angular/core";
22

3-
import {DBVIEW_MODULE_ENTRY_COMPONENT_TOKEN, DbViewEntryComponentInterface} from "src/web/browser-window/app/app.constants";
3+
import {DBVIEW_MODULE_ENTRY_COMPONENT_TOKEN} from "src/web/browser-window/app/app.constants";
44
import {DbAccountPk} from "src/shared/model/database";
55

6+
type DbViewEntryComponent = import("src/web/browser-window/app/_db-view/db-view-entry.component").DbViewEntryComponent;
7+
68
@Injectable()
79
export class DbViewModuleResolve {
810

911
private state: {
10-
resolveComponentFactory: () => Promise<ComponentFactory<DbViewEntryComponentInterface>>;
12+
resolveComponentFactory: () => Promise<ComponentFactory<DbViewEntryComponent>>;
1113
} = {
1214
resolveComponentFactory: async () => {
13-
const moduleFactory = await this.moduleLoader.load("./_db-view/db-view.module#DbViewModule");
15+
const {DbViewModule} = await import("src/web/browser-window/app/_db-view/db-view.module");
16+
const compiler = this.injector.get(Compiler);
17+
const moduleFactory = await compiler.compileModuleAsync(DbViewModule);
1418
const moduleRef = moduleFactory.create(this.injector);
1519
const component = moduleRef.injector.get(DBVIEW_MODULE_ENTRY_COMPONENT_TOKEN);
1620
const componentFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(component);
@@ -23,15 +27,18 @@ export class DbViewModuleResolve {
2327
};
2428

2529
constructor(
26-
private moduleLoader: NgModuleFactoryLoader,
2730
private injector: Injector,
2831
) {}
2932

30-
async buildComponentRef(dbAccountPk: DbAccountPk): Promise<ComponentRef<DbViewEntryComponentInterface>> {
33+
async mountDbViewEntryComponent(
34+
container: ViewContainerRef,
35+
dbAccountPk: DbAccountPk,
36+
): Promise<ComponentRef<DbViewEntryComponent>> {
3137
const componentFactory = await this.state.resolveComponentFactory();
32-
const componentRef = componentFactory.create(this.injector);
38+
const componentRef = container.createComponent(componentFactory);
3339

3440
componentRef.instance.dbAccountPk = dbAccountPk;
41+
componentRef.changeDetectorRef.detectChanges();
3542

3643
return componentRef;
3744
}

src/web/browser-window/app/_db-view/db-view-entry.component.ts

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,31 @@
1-
import {ChangeDetectionStrategy, Component, ElementRef, Input, OnDestroy, OnInit, Renderer2} from "@angular/core";
1+
import {ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit} from "@angular/core";
22
import {Deferred} from "ts-deferred";
33
import {Store} from "@ngrx/store";
44

55
import {DB_VIEW_ACTIONS} from "src/web/browser-window/app/store/actions";
66
import {DbAccountPk} from "src/shared/model/database";
7-
import {DbViewEntryComponentInterface} from "src/web/browser-window/app/app.constants";
87
import {State} from "src/web/browser-window/app/store/reducers/db-view";
98

10-
type ComponentInterface = Pick<DbViewEntryComponentInterface, Extract<keyof DbViewEntryComponentInterface, string>>;
11-
129
@Component({
1310
selector: "electron-mail-db-view-entry",
1411
templateUrl: "./db-view-entry.component.html",
1512
styleUrls: ["./db-view-entry.component.scss"],
1613
changeDetection: ChangeDetectionStrategy.OnPush,
1714
})
18-
export class DbViewEntryComponent implements ComponentInterface, OnDestroy, OnInit {
15+
export class DbViewEntryComponent implements OnDestroy, OnInit {
1916
@Input()
2017
dbAccountPk!: DbAccountPk;
2118

2219
private finishDeferred = new Deferred<void>();
2320

2421
constructor(
2522
private store: Store<State>,
26-
private renderer: Renderer2,
27-
private el: ElementRef,
2823
) {}
2924

3025
ngOnInit() {
3126
this.store.dispatch(DB_VIEW_ACTIONS.MountInstance({dbAccountPk: this.dbAccountPk, finishPromise: this.finishDeferred.promise}));
3227
}
3328

34-
setVisibility(value: boolean) {
35-
this.renderer.setStyle(this.el.nativeElement, "display", value ? "flex" : "none");
36-
}
37-
3829
ngOnDestroy() {
3930
this.finishDeferred.resolve();
4031
this.store.dispatch(DB_VIEW_ACTIONS.UnmountInstance({dbAccountPk: this.dbAccountPk}));

src/web/browser-window/app/app.constants.ts

+4-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import {InjectionToken} from "@angular/core";
1+
import {InjectionToken, Type} from "@angular/core";
22
import {Subject} from "rxjs";
33

4-
import {DbAccountPk} from "src/shared/model/database";
54
import {LoginFieldContainer} from "src/shared/model/container";
65

76
export const STUB_OUTLET = "stub-outlet";
@@ -26,11 +25,6 @@ export const ROUTER_DATA_OUTLET_PROP = "ROUTER_DATA_OUTLET_PROP";
2625

2726
export const FIRE_SYNCING_ITERATION$ = new Subject<LoginFieldContainer>();
2827

29-
export interface DbViewEntryComponentInterface {
30-
dbAccountPk: DbAccountPk;
31-
32-
// tslint:disable-next-line:no-misused-new
33-
new(...args: any[]): DbViewEntryComponentInterface;
34-
}
35-
36-
export const DBVIEW_MODULE_ENTRY_COMPONENT_TOKEN = new InjectionToken<DbViewEntryComponentInterface>("DbViewEntryComponent");
28+
export const DBVIEW_MODULE_ENTRY_COMPONENT_TOKEN
29+
// tslint:disable-next-line:max-line-length
30+
= new InjectionToken<Type<import("src/web/browser-window/app/_db-view/db-view-entry.component").DbViewEntryComponent>>("DbViewEntryComponent");

webpack-configs/web/browser-window.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ const config = buildBaseWebConfig(
7979
discoverLazyRoutes: true, // TODO disable "discoverLazyRoutes" once switched to Ivy renderer
8080
directTemplateLoading: false,
8181
entryModule: `${browserWindowAppPath("./app.module")}#AppModule`,
82-
additionalLazyModules: {
83-
["./_db-view/db-view.module#DbViewModule"]: browserWindowAppPath("./_db-view/db-view.module.ts"),
84-
},
8582
}),
8683
],
8784
optimization: {
@@ -92,6 +89,11 @@ const config = buildBaseWebConfig(
9289
name: "vendor",
9390
chunks: "all",
9491
},
92+
"_db-view": {
93+
test: /src[\\/]web[\\/]browser-window[\\/]app[\\/]_db-view/,
94+
name: "_db-view",
95+
chunks: "all",
96+
},
9597
},
9698
},
9799
},

0 commit comments

Comments
 (0)