diff --git a/goldens/size-test.yaml b/goldens/size-test.yaml
index adfbd99cb03d..ab4c6b264bc0 100644
--- a/goldens/size-test.yaml
+++ b/goldens/size-test.yaml
@@ -1,2 +1,3 @@
material/list/nav-list: 130473
material/radio/without-group: 121448
+material/menu/without-lazy-content: 210751
diff --git a/integration/size-test/material/menu/BUILD.bazel b/integration/size-test/material/menu/BUILD.bazel
new file mode 100644
index 000000000000..b05792da3d1d
--- /dev/null
+++ b/integration/size-test/material/menu/BUILD.bazel
@@ -0,0 +1,7 @@
+load("//integration/size-test:index.bzl", "size_test")
+
+size_test(
+ name = "without-lazy-content",
+ file = "without-lazy-content.ts",
+ deps = ["//src/material/menu"],
+)
diff --git a/integration/size-test/material/menu/without-lazy-content.ts b/integration/size-test/material/menu/without-lazy-content.ts
new file mode 100644
index 000000000000..4c1fb39012df
--- /dev/null
+++ b/integration/size-test/material/menu/without-lazy-content.ts
@@ -0,0 +1,24 @@
+import {Component, NgModule} from '@angular/core';
+import {MatMenuModule} from '@angular/material/menu';
+import {platformBrowser} from '@angular/platform-browser';
+
+/**
+ * Basic component using `MatMenu` and `MatMenuTrigger`. No lazy `MatMenuContent` is
+ * specified, so it should be tree-shaken away.
+ */
+@Component({
+ template: `
+
+
+ `,
+})
+export class TestComponent {}
+
+@NgModule({
+ imports: [MatMenuModule],
+ declarations: [TestComponent],
+ bootstrap: [TestComponent],
+})
+export class AppModule {}
+
+platformBrowser().bootstrapModule(AppModule);
diff --git a/src/material/menu/menu-content.ts b/src/material/menu/menu-content.ts
index 83c16daa374b..be4281eee281 100644
--- a/src/material/menu/menu-content.ts
+++ b/src/material/menu/menu-content.ts
@@ -14,6 +14,7 @@ import {
ComponentFactoryResolver,
Directive,
Inject,
+ InjectionToken,
Injector,
OnDestroy,
TemplateRef,
@@ -21,11 +22,19 @@ import {
} from '@angular/core';
import {Subject} from 'rxjs';
+/**
+ * Injection token that can be used to reference instances of `MatMenuContent`. It serves
+ * as alternative token to the actual `MatMenuContent` class which could cause unnecessary
+ * retention of the class and its directive metadata.
+ */
+export const MAT_MENU_CONTENT = new InjectionToken('MatMenuContent');
+
/**
* Menu content that will be rendered lazily once the menu is opened.
*/
@Directive({
- selector: 'ng-template[matMenuContent]'
+ selector: 'ng-template[matMenuContent]',
+ providers: [{provide: MAT_MENU_CONTENT, useExisting: MatMenuContent}],
})
export class MatMenuContent implements OnDestroy {
private _portal: TemplatePortal;
diff --git a/src/material/menu/menu.ts b/src/material/menu/menu.ts
index f700730b6dc0..f672fa2c6775 100644
--- a/src/material/menu/menu.ts
+++ b/src/material/menu/menu.ts
@@ -43,7 +43,7 @@ import {
import {merge, Observable, Subject, Subscription} from 'rxjs';
import {startWith, switchMap, take} from 'rxjs/operators';
import {matMenuAnimations} from './menu-animations';
-import {MatMenuContent} from './menu-content';
+import {MAT_MENU_CONTENT, MatMenuContent} from './menu-content';
import {MenuPositionX, MenuPositionY} from './menu-positions';
import {throwMatMenuInvalidPositionX, throwMatMenuInvalidPositionY} from './menu-errors';
import {MatMenuItem} from './menu-item';
@@ -179,11 +179,12 @@ export class _MatMenuBase implements AfterContentInit, MatMenuPanel
*/
@ContentChildren(MatMenuItem, {descendants: false}) items: QueryList;
+ // TODO: Remove cast once https://github.com/angular/angular/pull/37506 is available.
/**
* Menu content that will be rendered lazily.
* @docs-private
*/
- @ContentChild(MatMenuContent) lazyContent: MatMenuContent;
+ @ContentChild(MAT_MENU_CONTENT as any) lazyContent: MatMenuContent;
/** Whether the menu should overlap its trigger. */
@Input()
diff --git a/tools/public_api_guard/material/menu.d.ts b/tools/public_api_guard/material/menu.d.ts
index b4167e72f340..24a5cf0c1e97 100644
--- a/tools/public_api_guard/material/menu.d.ts
+++ b/tools/public_api_guard/material/menu.d.ts
@@ -65,6 +65,8 @@ export declare class _MatMenuDirectivesModule {
export declare const fadeInItems: AnimationTriggerMetadata;
+export declare const MAT_MENU_CONTENT: InjectionToken;
+
export declare const MAT_MENU_DEFAULT_OPTIONS: InjectionToken;
export declare const MAT_MENU_PANEL: InjectionToken>;