Skip to content

Commit 738e514

Browse files
authored
perf(material/core): tree shake sanity checks (#23969)
Now that we don't need to think about ViewEngine, we can use `ngDevMode` to tree shake the sanity check messages.
1 parent 62f4370 commit 738e514

File tree

2 files changed

+65
-74
lines changed

2 files changed

+65
-74
lines changed

src/material/core/common-behaviors/common-module.ts

+64-72
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import {HighContrastModeDetector} from '@angular/cdk/a11y';
1010
import {BidiModule} from '@angular/cdk/bidi';
11-
import {Inject, InjectionToken, isDevMode, NgModule, Optional, Version} from '@angular/core';
11+
import {Inject, InjectionToken, NgModule, Optional, Version} from '@angular/core';
1212
import {VERSION as CDK_VERSION} from '@angular/cdk';
1313
import {DOCUMENT} from '@angular/common';
1414
import {_isTestEnvironment} from '@angular/cdk/platform';
@@ -57,42 +57,37 @@ export class MatCommonModule {
5757
/** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */
5858
private _hasDoneGlobalChecks = false;
5959

60-
/** Configured sanity checks. */
61-
private _sanityChecks: SanityChecks;
62-
63-
/** Used to reference correct document/window */
64-
protected _document: Document;
65-
6660
constructor(
6761
highContrastModeDetector: HighContrastModeDetector,
68-
@Optional() @Inject(MATERIAL_SANITY_CHECKS) sanityChecks: any,
69-
@Inject(DOCUMENT) document: any,
62+
@Optional() @Inject(MATERIAL_SANITY_CHECKS) private _sanityChecks: SanityChecks,
63+
@Inject(DOCUMENT) private _document: Document,
7064
) {
71-
this._document = document;
72-
7365
// While A11yModule also does this, we repeat it here to avoid importing A11yModule
7466
// in MatCommonModule.
7567
highContrastModeDetector._applyBodyHighContrastModeCssClasses();
7668

77-
// Note that `_sanityChecks` is typed to `any`, because AoT
78-
// throws an error if we use the `SanityChecks` type directly.
79-
this._sanityChecks = sanityChecks;
80-
8169
if (!this._hasDoneGlobalChecks) {
82-
this._checkDoctypeIsDefined();
83-
this._checkThemeIsPresent();
84-
this._checkCdkVersionMatch();
8570
this._hasDoneGlobalChecks = true;
71+
72+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
73+
if (this._checkIsEnabled('doctype')) {
74+
_checkDoctypeIsDefined(this._document);
75+
}
76+
77+
if (this._checkIsEnabled('theme')) {
78+
_checkThemeIsPresent(this._document);
79+
}
80+
81+
if (this._checkIsEnabled('version')) {
82+
_checkCdkVersionMatch();
83+
}
84+
}
8685
}
8786
}
8887

8988
/** Gets whether a specific sanity check is enabled. */
9089
private _checkIsEnabled(name: keyof GranularSanityChecks): boolean {
91-
// TODO(crisbeto): we can't use `ngDevMode` here yet, because ViewEngine apps might not support
92-
// it. Since these checks can have performance implications and they aren't tree shakeable
93-
// in their current form, we can leave the `isDevMode` check in for now.
94-
// tslint:disable-next-line:ban
95-
if (!isDevMode() || _isTestEnvironment()) {
90+
if (_isTestEnvironment()) {
9691
return false;
9792
}
9893

@@ -102,60 +97,57 @@ export class MatCommonModule {
10297

10398
return !!this._sanityChecks[name];
10499
}
100+
}
105101

106-
private _checkDoctypeIsDefined(): void {
107-
if (this._checkIsEnabled('doctype') && !this._document.doctype) {
108-
console.warn(
109-
'Current document does not have a doctype. This may cause ' +
110-
'some Angular Material components not to behave as expected.',
111-
);
112-
}
102+
/** Checks that the page has a doctype. */
103+
function _checkDoctypeIsDefined(doc: Document): void {
104+
if (!doc.doctype) {
105+
console.warn(
106+
'Current document does not have a doctype. This may cause ' +
107+
'some Angular Material components not to behave as expected.',
108+
);
113109
}
110+
}
114111

115-
private _checkThemeIsPresent(): void {
116-
// We need to assert that the `body` is defined, because these checks run very early
117-
// and the `body` won't be defined if the consumer put their scripts in the `head`.
118-
if (
119-
!this._checkIsEnabled('theme') ||
120-
!this._document.body ||
121-
typeof getComputedStyle !== 'function'
122-
) {
123-
return;
124-
}
125-
126-
const testElement = this._document.createElement('div');
127-
128-
testElement.classList.add('mat-theme-loaded-marker');
129-
this._document.body.appendChild(testElement);
130-
131-
const computedStyle = getComputedStyle(testElement);
132-
133-
// In some situations the computed style of the test element can be null. For example in
134-
// Firefox, the computed style is null if an application is running inside of a hidden iframe.
135-
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=548397
136-
if (computedStyle && computedStyle.display !== 'none') {
137-
console.warn(
138-
'Could not find Angular Material core theme. Most Material ' +
139-
'components may not work as expected. For more info refer ' +
140-
'to the theming guide: https://material.angular.io/guide/theming',
141-
);
142-
}
112+
/** Checks that a theme has been included. */
113+
function _checkThemeIsPresent(doc: Document): void {
114+
// We need to assert that the `body` is defined, because these checks run very early
115+
// and the `body` won't be defined if the consumer put their scripts in the `head`.
116+
if (!doc.body || typeof getComputedStyle !== 'function') {
117+
return;
118+
}
143119

144-
testElement.remove();
120+
const testElement = doc.createElement('div');
121+
testElement.classList.add('mat-theme-loaded-marker');
122+
doc.body.appendChild(testElement);
123+
124+
const computedStyle = getComputedStyle(testElement);
125+
126+
// In some situations the computed style of the test element can be null. For example in
127+
// Firefox, the computed style is null if an application is running inside of a hidden iframe.
128+
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=548397
129+
if (computedStyle && computedStyle.display !== 'none') {
130+
console.warn(
131+
'Could not find Angular Material core theme. Most Material ' +
132+
'components may not work as expected. For more info refer ' +
133+
'to the theming guide: https://material.angular.io/guide/theming',
134+
);
145135
}
146136

147-
/** Checks whether the material version matches the cdk version */
148-
private _checkCdkVersionMatch(): void {
149-
if (this._checkIsEnabled('version') && VERSION.full !== CDK_VERSION.full) {
150-
console.warn(
151-
'The Angular Material version (' +
152-
VERSION.full +
153-
') does not match ' +
154-
'the Angular CDK version (' +
155-
CDK_VERSION.full +
156-
').\n' +
157-
'Please ensure the versions of these two packages exactly match.',
158-
);
159-
}
137+
testElement.remove();
138+
}
139+
140+
/** Checks whether the Material version matches the CDK version. */
141+
function _checkCdkVersionMatch(): void {
142+
if (VERSION.full !== CDK_VERSION.full) {
143+
console.warn(
144+
'The Angular Material version (' +
145+
VERSION.full +
146+
') does not match ' +
147+
'the Angular CDK version (' +
148+
CDK_VERSION.full +
149+
').\n' +
150+
'Please ensure the versions of these two packages exactly match.',
151+
);
160152
}
161153
}

tools/public_api_guard/material/core.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,7 @@ export const MAT_RIPPLE_GLOBAL_OPTIONS: InjectionToken<RippleGlobalOptions>;
188188

189189
// @public
190190
export class MatCommonModule {
191-
constructor(highContrastModeDetector: HighContrastModeDetector, sanityChecks: any, document: any);
192-
protected _document: Document;
191+
constructor(highContrastModeDetector: HighContrastModeDetector, _sanityChecks: SanityChecks, _document: Document);
193192
// (undocumented)
194193
static ɵfac: i0.ɵɵFactoryDeclaration<MatCommonModule, [null, { optional: true; }, null]>;
195194
// (undocumented)

0 commit comments

Comments
 (0)