changed 6 years ago
Linked with GitHub

Static-query migration strategies

There are two ways of how we can migrate existing Angular applications to
the new ViewChild and ContentChild static timing syntax. Either by:

  1. Looking at the current usage of the query
  2. Inspecting what the query selects in the component template

Both approaches have benefits and downsides which are summarized here:

Approach 1 (query usage)

Positives:

  • Best practices as we don't mark queries as static if they don't need to be (e.g. for Ivy)
  • Can detect ContentChild query timing if used statically (for most cases: see negatives)

Negatives:

  • Limited coverage of application. e.g. queries could be accessed in other parts
    of the project. e.g. through dependency injection.
    • These cases can be handled technically but there a lot of edge-cases that
      need to be handled and this degenerates into a runtime Angular application
      simulator eventually (e.g. template component scope, virtual injector tree)
    • e.g. Testing code accessed the query before running fixture.detectChanges
  • Lots of code needed for detection of query usage through TypeScript AST and type checking.

Approach 2 (template selection)

Positives:

  • Guaranteed to determine working timing for ViewQuery due to the template analysis.
  • Easy to implement. Less code needed as template AST can be visited and used to determine
    query timing

Negatives:

  • Difficult to determine query timing for ContentChild since projected content can
    be inserted from anywhere:
    • This could technically be handled, but in order to handle that we need to analyze
      all other components that project content into the given component. This is nearly
      impossible as other Angular projects, which are not statically analyzable, can also
      project content into the component. Therefore the prediction is never 100% correct.
    • The Angular compiler can only time the content queries properly at runtime when the
      projected content and the component hierarchy is already known.
  • Due to queries marked too aggressively, it makes the template inflexible to future changes.

Usage strategy

We analyze the query usage and check if we find a static query usage. If we
definitely found a static query usage, we mark the query as static.

If we are unsure about it being static (e.g. through a third-party callback function), the
query timing is ambiguous and we mark it as static with a TODO that requires the developer
to double-check if the query could technically be marked as dynamic (e.g. for simpler
Ivy migration in the future)

If we didn't find any static query usage, the query is still not definitely dynamic, as
the query could be still referenced somewhere else (e.g. dependency injection). In that
case the query timing is dynamic and we just add an inline todo asking the developer to
double-check if the query is used somewhere statically.

Template selection strategy

For ViewChild queries, we analyze the template and use the view engine sorting in order
to provide a guaranteed working migration for that view query.

For ContentChild queries, we can never determine a working/correct query timing with this
strategy and can just leave the decision up to the developer by adding an inline TODO.

Implementation requirements:

  • Need to handle queries that select component/directives instead of template references.
    • Requires us to determine selectors of specified component/directives identifiers.
    • Requires us to work with third-party modules through metadata files.

Mixed strategy

For ViewChild queries, we use the template selection strategy in order to get a 100% working
migration for these queries.

For ContentChild queries, we check if the query is statically used. If not, we fallback to the
template selection strategy and just add an inline todo and leave the decision up to the
developer. This allows us to correctly handle the migration for ContentChild in some cases as
well. Meaning that this strategy has:

  • 100% validity and 100% migration-rate for view queries
  • 100% validity and ~25% migration-rate for content queries

The 25% are determined by estimating that 50% content queries are statically
used in an application and that the query usage detection has a 50% migration-rate.
(as it cannot always detect query usage due to various edge-cases)


General todo's

Select a repo