Extended Diagnostics

Defer Trigger Misconfiguration

This diagnostic detects unreachable or redundant triggers in @defer blocks.

import {Component} from '@angular/core';

@Component({
  template: `
    @defer (on immediate; on timer(500ms)) {
      <large-component />
    }
  `,
})
class MyComponent {}

What's wrong with that?

The diagnostic identifies several problematic patterns in defer trigger configuration that lead to:

  • Unnecessary code that never affects behavior
  • Missed optimization opportunities for better performance
  • Unreachable prefetch triggers that will never execute

Diagnostic warning cases

This diagnostic flags the following problematic patterns:

immediate with prefetch triggers

Avoid

prefetch never runs

@Component({
  template: `
    @defer (on immediate; prefetch on idle) {
      <my-cmp />
    }
  `,
})
class MyComponent {}
Prefer

remove redundant prefetch

@Component({
  template: `
    @defer (on immediate) {
      <my-cmp />
    }
  `,
})
class MyComponent {}

Prefetch timer not earlier than main timer

Avoid

prefetch is later than main

@Component({
  template: `
    @defer (on timer(100ms); prefetch on timer(3000ms)) {
      <my-cmp />
    }
  `,
})
class MyComponent {}
Avoid

equal timing provides no benefit

@Component({
  template: `
    @defer (on timer(500ms); prefetch on timer(500ms)) {
      <my-cmp />
    }
  `,
})
class MyComponent {}
Prefer

prefetch fires earlier

@Component({
  template: `
    @defer (on timer(1000ms); prefetch on timer(500ms)) {
      <large-component />
    }
  `,
})
class MyComponent {}

Prefetch without main triggers

Avoid

unexpected early fetch

@Component({
  template: `
    @defer (prefetch when someFlag()) {
      <heavy-comp />
    }
  `,
})
class MyComponent {
  someFlag = signal(false);
}

This configuration may suggest that the prefetch will only run when someFlag becomes true. However, since the main trigger still defaults to on idle, the deferred content can be fetched earlier during the browser’s idle period, effectively bypassing the intended condition.

Prefer

explicitly define main trigger

@Component({
  template: `
    @defer (on interaction; prefetch when someFlag()) {
      <heavy-comp />
    }
  `,
})
class MyComponent {
  someFlag = signal(false);
}

Identical prefetch and main triggers

Avoid

identical viewport trigger

@Component({
  template: `
    @defer (on viewport; prefetch on viewport) {
      <my-cmp />
    }
  `,
})
class MyComponent {}
Avoid

identical interaction target

@Component({
  template: `
    <button #loadBtn>Load</button>
    @defer (on interaction(loadBtn); prefetch on interaction(loadBtn)) {
      <large-component />
    }
  `,
})
class MyComponent {}
Prefer

remove redundant prefetch

@Component({
  template: `
    <button #loadBtn>Load</button>
    @defer (on interaction(loadBtn)) {
      <large-component />
    }
  `,
})
class MyComponent {}
Prefer

use different targets for prefetch and main

@Component({
  template: `
    <div #hoverArea>Hover to prefetch</div>
    <button #clickBtn>Click to load</button>
    @defer (on interaction(clickBtn); prefetch on hover(hoverArea)) {
      <large-component />
    }
  `,
})
class MyComponent {}

Configuration requirements

strictTemplates must be enabled for any extended diagnostic to emit. deferTriggerMisconfiguration has no additional requirements beyond strictTemplates.

What if I can't avoid this?

This diagnostic can be disabled by editing the project's tsconfig.json file:

{
  "angularCompilerOptions": {
    "extendedDiagnostics": {
      "checks": {
        "deferTriggerMisconfiguration": "suppress"
      }
    }
  }
}

See extended diagnostic configuration for more info.