Search code examples
angulartypescriptstatic-analysis

In Angular, how to identify what components are used by what routes, via static analysis of the code


I'm trying to make sense of a large Angular application and document it. I would like first and foremost to match components to routes, that is, to know what components are run to build a given "screen" identified by a route, and handle all the different user actions that can happen in that screen before the route changes.

I would like to do this with a static analysis of the TS code, without running the application and without doing any pre-compiling.

Compodoc would seem to be quite useful for this, but it fails to correctly parse routing files and so doesn't output any route. The project seems a little dead-ish and many issues stay unresolved.

ngrev also fails immediately and doesn't output anything.

I have written some code in JavaScript that uses the AST output of the TypeScript parser that lists all the routes of the application (by following lazy-loading modules, etc.), and identifies all modules and components.

But given the above, is it possible to enumerate all components involved in building a screen, via a pure static analysis, without running the application and without doing some pre-compiling and the like? Or, how far can static analysis go, and what may it miss?

Does it make sense to follow component declarations and imports, from the root module to the current screen?


Solution

  • This can be a rather complex task, so maybe the way to go is breaking it into smaller ones.

    1. Identify the components mapped to each route.
    2. Given a component class, find the template associated with it. Note that the template might be defined inline or in a separate file.
    3. Given the code for a template, find all components tags (selectors) referenced on it.
    4. Given a component selector, find the class associated with it. Note that it might be a component defined on your project or from an external library.

    This will probably cover most use cases, unless you're doing some dynamic component rendering operations.

    You might also want to look at the components referenced on the TypeScript code, you'll probably find usages like this:

    openDialog() {
      this.dialogService.open(MyDialogComponent)
    }