Skip to content

Commit 71b8963

Browse files
committed
fix(material-angular-io): remove docs data from critical path
The docs site was loading the data of all the examples up-front through an eager import which was bringing in ~170kb of JavaScript which isn't necessary for the initial load. These changes refactor the various call sites so that they load the example data asynchronously.
1 parent 546babd commit 71b8963

File tree

15 files changed

+205
-310
lines changed

15 files changed

+205
-310
lines changed

material.angular.io/.eslintrc.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@
2020
"@angular-eslint/component-selector": "off",
2121
"@angular-eslint/directive-class-suffix": "off",
2222
"@angular-eslint/directive-selector": "off",
23+
"@angular-eslint/no-host-metadata-property": "off",
2324
"@typescript-eslint/dot-notation": "off",
2425
"@typescript-eslint/member-delimiter-style": "off",
26+
"@typescript-eslint/naming-convention": "off",
2527
"@typescript-eslint/explicit-member-accessibility": [
2628
"off",
2729
{

material.angular.io/src/app/pages/component-category-list/component-category-list.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
focusOnNavigation>
44
<div [innerHTML]="_categoryListSummary"></div>
55
</div>
6-
@if ((params | async)?.section; as section) {
6+
@if (items.length > 0) {
77
<div class="docs-component-category-list">
8-
@for (component of docItems.getItems(section); track component) {
8+
@for (component of items; track component) {
99
<a class="docs-component-category-list-item"
1010
[routerLink]="'/' + section + '/' + component.id">
1111
<div class="docs-component-category-list-card" matRipple>

material.angular.io/src/app/pages/component-category-list/component-category-list.spec.ts

Lines changed: 0 additions & 41 deletions
This file was deleted.

material.angular.io/src/app/pages/component-category-list/component-category-list.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
import {AsyncPipe} from '@angular/common';
21
import {Component, NgModule, OnDestroy, OnInit} from '@angular/core';
32
import {MatCardModule} from '@angular/material/card';
4-
import {ActivatedRoute, Params, RouterModule, RouterLink} from '@angular/router';
3+
import {ActivatedRoute, RouterModule, RouterLink} from '@angular/router';
54
import {MatRipple} from '@angular/material/core';
6-
import {combineLatest, Observable, Subscription} from 'rxjs';
5+
import {combineLatest, Subscription} from 'rxjs';
76

8-
import {DocumentationItems, SECTIONS} from '../../shared/documentation-items/documentation-items';
7+
import {
8+
DocItem,
9+
DocumentationItems,
10+
SECTIONS,
11+
} from '../../shared/documentation-items/documentation-items';
912
import {NavigationFocus} from '../../shared/navigation-focus/navigation-focus';
1013

1114
import {ComponentPageTitle} from '../page-title/page-title';
@@ -15,32 +18,31 @@ import {ComponentPageTitle} from '../page-title/page-title';
1518
templateUrl: './component-category-list.html',
1619
styleUrls: ['./component-category-list.scss'],
1720
standalone: true,
18-
imports: [NavigationFocus, RouterLink, AsyncPipe, MatRipple],
21+
imports: [NavigationFocus, RouterLink, MatRipple],
1922
})
2023
export class ComponentCategoryList implements OnInit, OnDestroy {
21-
params: Observable<Params> | undefined;
24+
items: DocItem[] = [];
25+
section = '';
2226
routeParamSubscription: Subscription = new Subscription();
2327
_categoryListSummary: string | undefined;
2428

2529
constructor(
26-
public docItems: DocumentationItems,
27-
public _componentPageTitle: ComponentPageTitle,
30+
readonly _docItems: DocumentationItems,
31+
private _componentPageTitle: ComponentPageTitle,
2832
private _route: ActivatedRoute,
2933
) {}
3034

3135
ngOnInit() {
32-
// Combine params from all of the path into a single object.
33-
this.params = combineLatest(
36+
this.routeParamSubscription = combineLatest(
3437
this._route.pathFromRoot.map(route => route.params),
3538
Object.assign,
36-
);
37-
38-
// title on topbar navigation
39-
this.routeParamSubscription = this.params.subscribe(params => {
39+
).subscribe(async params => {
4040
const sectionName = params['section'];
4141
const section = SECTIONS[sectionName];
4242
this._componentPageTitle.title = section.name;
4343
this._categoryListSummary = section.summary;
44+
this.section = sectionName;
45+
this.items = await this._docItems.getItems(sectionName);
4446
});
4547
}
4648

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
<div class="docs-component-viewer-nav">
2-
@if ((params() | async)?.section; as section) {
2+
@let items = (this.items | async) || [];
3+
4+
@if (items.length > 0) {
35
<div class="docs-component-viewer-nav-content">
4-
<mat-nav-list>
5-
@for (component of docItems.getItems(section); track component) {
6-
<a mat-list-item #link="routerLinkActive"
7-
[routerLink]="'/' + section+ '/' + component.id"
8-
[activated]="link.isActive"
9-
routerLinkActive="docs-component-viewer-sidenav-item-selected"
10-
[attr.aria-current]="currentItemId === component.id ? 'page': 'false'">
11-
{{component.name}}
12-
</a>
13-
}
14-
</mat-nav-list>
6+
<mat-nav-list>
7+
@for (component of items; track component) {
8+
<a mat-list-item #link="routerLinkActive"
9+
[routerLink]="'/' + params()?.section + '/' + component.id"
10+
[activated]="link.isActive"
11+
routerLinkActive="docs-component-viewer-sidenav-item-selected"
12+
[attr.aria-current]="link.isActive ? 'page': 'false'">
13+
{{component.name}}
14+
</a>
15+
}
16+
</mat-nav-list>
1517
</div>
1618
}
1719
</div>

material.angular.io/src/app/pages/component-sidenav/component-sidenav.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[mode]="(isScreenSmall | async) ? 'over' : 'side'"
77
[fixedInViewport]="(isScreenSmall | async)"
88
[fixedTopGap]="(isExtraScreenSmall | async) ? 92 : 56">
9-
<app-component-nav [params]="params"></app-component-nav>
9+
<app-component-nav [params]="params | async"></app-component-nav>
1010
</mat-sidenav>
1111
}
1212
<div class="docs-component-sidenav-content">
@@ -15,7 +15,7 @@
1515
<main class="docs-component-sidenav-body-content">
1616
<!-- If on large screen, menu resides to left of content -->
1717
@if ((isScreenSmall | async) === false) {
18-
<app-component-nav [params]="params"/>
18+
<app-component-nav [params]="params | async"/>
1919
}
2020
<router-outlet></router-outlet>
2121
</main>

material.angular.io/src/app/pages/component-sidenav/component-sidenav.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ describe('ComponentSidenav', () => {
3434
});
3535
});
3636

37-
it('should show a link for each item in doc items categories', () => {
38-
const totalItems = component.docItems.getItems('categories').length;
37+
it('should show a link for each item in doc items categories', async () => {
38+
const items = await component.docItems.getItems('categories');
39+
const totalItems = items.length;
3940
const totalLinks = fixture.nativeElement.querySelectorAll(
4041
'.docs-component-viewer-sidenav li a',
4142
).length;

material.angular.io/src/app/pages/component-sidenav/component-sidenav.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import {
22
Component,
33
NgModule,
4-
NgZone,
54
OnDestroy,
65
OnInit,
76
ViewEncapsulation,
87
forwardRef,
8+
inject,
99
input,
1010
viewChild,
1111
} from '@angular/core';
12+
import {toObservable} from '@angular/core/rxjs-interop';
1213
import {CdkAccordionModule} from '@angular/cdk/accordion';
1314
import {BreakpointObserver} from '@angular/cdk/layout';
1415
import {AsyncPipe} from '@angular/common';
@@ -26,7 +27,7 @@ import {
2627
RouterLink,
2728
} from '@angular/router';
2829
import {combineLatest, Observable, Subscription} from 'rxjs';
29-
import {map} from 'rxjs/operators';
30+
import {map, switchMap} from 'rxjs/operators';
3031

3132
import {DocViewerModule} from '../../shared/doc-viewer/doc-viewer-module';
3233
import {DocumentationItems} from '../../shared/documentation-items/documentation-items';
@@ -75,16 +76,15 @@ const SMALL_WIDTH_BREAKPOINT = 959;
7576
})
7677
export class ComponentSidenav implements OnInit, OnDestroy {
7778
readonly sidenav = viewChild(MatSidenav);
78-
params: Observable<Params> | undefined;
79+
params: Observable<Params>;
7980
isExtraScreenSmall: Observable<boolean>;
8081
isScreenSmall: Observable<boolean>;
81-
private subscriptions = new Subscription();
82+
private _subscriptions = new Subscription();
8283

8384
constructor(
8485
public docItems: DocumentationItems,
8586
private _route: ActivatedRoute,
8687
private _navigationFocusService: NavigationFocusService,
87-
zone: NgZone,
8888
breakpoints: BreakpointObserver,
8989
) {
9090
this.isExtraScreenSmall = breakpoints
@@ -93,16 +93,15 @@ export class ComponentSidenav implements OnInit, OnDestroy {
9393
this.isScreenSmall = breakpoints
9494
.observe(`(max-width: ${SMALL_WIDTH_BREAKPOINT}px)`)
9595
.pipe(map(breakpoint => breakpoint.matches));
96-
}
9796

98-
ngOnInit() {
99-
// Combine params from all of the path into a single object.
10097
this.params = combineLatest(
10198
this._route.pathFromRoot.map(route => route.params),
10299
Object.assign,
103100
);
101+
}
104102

105-
this.subscriptions.add(
103+
ngOnInit() {
104+
this._subscriptions.add(
106105
this._navigationFocusService.navigationEndEvents
107106
.pipe(map(() => this.isScreenSmall))
108107
.subscribe(shouldCloseSideNav => {
@@ -115,7 +114,7 @@ export class ComponentSidenav implements OnInit, OnDestroy {
115114
}
116115

117116
ngOnDestroy() {
118-
this.subscriptions.unsubscribe();
117+
this._subscriptions.unsubscribe();
119118
}
120119

121120
toggleSidenav(): void {
@@ -130,10 +129,14 @@ export class ComponentSidenav implements OnInit, OnDestroy {
130129
imports: [MatListModule, RouterLinkActive, RouterLink, AsyncPipe],
131130
})
132131
export class ComponentNav {
133-
readonly params = input<Observable<Params>>();
134-
currentItemId: string | undefined;
132+
private _docItems = inject(DocumentationItems);
133+
readonly params = input<Params | null>();
135134

136-
constructor(public docItems: DocumentationItems) {}
135+
items = toObservable(this.params).pipe(
136+
switchMap(params =>
137+
params?.section ? this._docItems.getItems(params.section) : Promise.resolve(null),
138+
),
139+
);
137140
}
138141

139142
const routes: Routes = [

material.angular.io/src/app/pages/component-viewer/component-viewer.spec.ts

Lines changed: 0 additions & 54 deletions
This file was deleted.

material.angular.io/src/app/pages/component-viewer/component-viewer.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@ import {
1414
import {MatTabsModule} from '@angular/material/tabs';
1515
import {
1616
ActivatedRoute,
17-
Params,
1817
Router,
1918
RouterModule,
2019
RouterLinkActive,
2120
RouterLink,
2221
RouterOutlet,
2322
} from '@angular/router';
2423
import {combineLatest, Observable, ReplaySubject, Subject} from 'rxjs';
25-
import {map, skip, takeUntil} from 'rxjs/operators';
24+
import {map, skip, switchMap, takeUntil} from 'rxjs/operators';
2625
import {DocViewerModule} from '../../shared/doc-viewer/doc-viewer-module';
2726
import {DocItem, DocumentationItems} from '../../shared/documentation-items/documentation-items';
2827
import {TableOfContents} from '../../shared/table-of-contents/table-of-contents';
@@ -59,15 +58,13 @@ export class ComponentViewer implements OnDestroy {
5958
// parent route for the section (material/cdk).
6059
combineLatest(routeAndParentParams)
6160
.pipe(
62-
map((params: Params[]) => {
61+
switchMap(async params => {
6362
const id = params[0]['id'];
6463
const section = params[1]['section'];
65-
66-
return {
67-
doc: docItems.getItemById(id, section),
68-
section: section,
69-
};
70-
}, takeUntil(this._destroyed)),
64+
const doc = await docItems.getItemById(id, section);
65+
return {doc, section};
66+
}),
67+
takeUntil(this._destroyed),
7168
)
7269
.subscribe(({doc, section}) => {
7370
if (!doc) {

0 commit comments

Comments
 (0)