Skip to content

fix(compiler-cli): report NG8030 when a class-based query predicate blocks deferred lazy loading#69503

Draft
arturovt wants to merge 1 commit into
angular:mainfrom
arturovt:fix/compiler_cli_defer_broken
Draft

fix(compiler-cli): report NG8030 when a class-based query predicate blocks deferred lazy loading#69503
arturovt wants to merge 1 commit into
angular:mainfrom
arturovt:fix/compiler_cli_defer_broken

Conversation

@arturovt

Copy link
Copy Markdown
Contributor

When a component is placed exclusively inside a @defer block, Angular can split it into a separate lazy chunk. That optimization silently breaks if the same component is also used as a viewChild or contentChild predicate — the class reference in the query keeps the import eager, so the bundler never gets a chance to defer it.

This commit introduces error NG8030 (DEFERRED_COMPONENT_USED_IN_QUERY) that fires whenever the compiler detects this pattern during the resolve phase. The diagnostic points directly at the predicate expression and suggests the string-based alternative with a local template reference variable.

The check lives in the component handler's resolve phase rather than in packages/.../typecheck/extended/checks because it needs to cross-reference two pieces of data that only come together there: the deferred-per-block dependency map (which components are exclusively behind @defer) and the eagerlyUsedDecls set (which components are also used outside @defer, so they're already eager and there's nothing to warn about). The extendedTemplateCheck interface doesn't have access to either — it only sees the template AST and a type-check context.

The eagerlyUsedDecls guard is important: if a component appears both inside and outside a @defer block, the import is already eager regardless of the query, so no diagnostic is emitted.

@angular-robot angular-robot Bot added the area: compiler Issues related to `ngc`, Angular's template compiler label Jun 24, 2026
@ngbot ngbot Bot added this to the Backlog milestone Jun 24, 2026
@arturovt

Copy link
Copy Markdown
Contributor Author

@JeanMeche as discussed internally

…locks deferred lazy loading

When a component is placed exclusively inside a @defer block, Angular can split it into a
separate lazy chunk. That optimization silently breaks if the same component is also used as
a viewChild or contentChild predicate — the class reference in the query keeps the import
eager, so the bundler never gets a chance to defer it.

This commit introduces error NG8030 (DEFERRED_COMPONENT_USED_IN_QUERY) that fires whenever
the compiler detects this pattern during the resolve phase. The diagnostic points directly
at the predicate expression and suggests the string-based alternative with a local template
reference variable.

The check lives in the component handler's resolve phase rather than in
packages/.../typecheck/extended/checks because it needs to cross-reference two pieces of
data that only come together there: the deferred-per-block dependency map (which components
are exclusively behind @defer) and the eagerlyUsedDecls set (which components are also used
outside @defer, so they're already eager and there's nothing to warn about). The
extendedTemplateCheck interface doesn't have access to either — it only sees the template
AST and a type-check context.

The eagerlyUsedDecls guard is important: if a component appears both inside and outside a
@defer block, the import is already eager regardless of the query, so no diagnostic is
emitted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: compiler Issues related to `ngc`, Angular's template compiler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant