Repository: angular
Issue: Transition Angular from the whole-program compilation to localized compilation
Labels: action: discuss,area: compiler,needs: discussion

*Note 1: This proposal has its origin in [Out-of-band type-checking for TypeScript and Template compilation](https://github.com/angular/angular/issues/43131) which mentions an "extreme" implementation option — this issue provides more details about this option.*

*Note 2: 📺 Check out the [video recording of a community discussion about this proposal](https://youtu.be/FbJLC7GxAAs?t=5919) @ [angularnation.net](https://www.angularnation.net/)*

## The problem

As described in the [Out-of-band type-checking for TypeScript and Template compilation](https://github.com/angular/angular/issues/43131) proposal, making Angular's compilation model highly parallelizable would result in major benefits for Angular developers by **significantly lowering the interactive workflow latency** (making the "edit & refresh" cycle faster). 

This change would additionally **improve the efficiency (in time, and CPU cost) of building Angular at scale** in monorepos and on CI systems.

**The current cost of compilation is significant, and becoming a hurdle affecting DX, and our ability to scale massive code bases.**

## Background info

The unit of parallelization of Angular's compilation is the ["program" as defined by the TypeScript compiler](https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#a-minimal-compiler) — the program is the smallest unit of code (a group of `.ts`, `.d.ts`, and `.js` files declared and configured by a single [tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) file) that the TypeScript compiler can process independently of other code. 

A typical Angular compilation unit is a program that is composed of several (often many) components, directives, pipes, services, NgModules, and generic TypeScript files.

A small application is commonly built as a single program, that often depends on 3rd party Angular libraries (that themselves were compiled as individual programs). Larger code bases, split up their app into multiple programs using [Angular CLI workspaces](https://angular.io/guide/file-structure#multiple-projects), [Bazel's rules_nodejs](https://github.com/bazelbuild/rules_nodejs) (or the `ng_module` rule), or [Nx](https://nx.dev/).

These approaches to scaling help, but don't solve the ultimate problem, which is that *it is currently not possible to process a single Angular Component* and transform it to runnable JS without processing a bigger chunk of the code base as well (the whole program). This prevents us from taking advantage of massive parallelization that modern hardware in combination with highly parallelizable transpilation engines like [esbuild](https://esbuild.github.io/), (and [Vite](https://vitejs.dev/) built on top of it) and [Bazel](https://bazel.build) offer. This results in wasted human and CPU time and ultimately in loss of focus, creativity, and high CI bills.

## Proposed solution

Let's transition the processing model of Angular code from the "whole world" compilation model (global optimization), to localized compilation (and as close to transpilation as possible). In an extreme example, this would mean that a single `.ts` file with an Angular component could be converted to `.js`on its own without having to read or process any other files.

In practice, it's more likely that we'll need to read and process several files around this single `.ts` file because of references to external templates and style sheets, and we'll need the imported NgModules and (upcoming "standalone components, directives, and pipes" — [check out the RFC](https://github.com/angular/angular/discussions/43784)) to be at least read, if not compiled as well, because they represent transitive dependencies of the component being processed.

Aiming for purely syntactic transpilation of template and metadata to JavaScript code would most likely be a "bridge too far" (see "Alternatives considered" below), but getting as close as possible to that ideal is at the core of this proposal.

We don't need purely syntactic transpilation to still reap most of the benefits of parallelization, localized compilation would result in a huge improvement already. 

## Implementation details

- [Out-of-band type-checking for TypeScript and Template compilation](https://github.com/angular/angular/issues/43131) is a most likely a prerequisite for this project, because we need to decouple type-checking from code generation.
- Moving away from NgModules, to [module-less, a.k.a. "standalone" components, directives, and pipes](https://github.com/angular/angular/discussions/43784) would provide us with focused understand the context within which a component or a directive are being compiled — fortunately we want to execute on this project regardless of this proposal in order to reduce verbosity and complexity of Angular, so this prerequisite is well aligned with our ongoing work.
- We'd need to rethink our compiler architecture, and investigate if building it on top of the TypeScript AST is the right approach or if we should consider more lightweight alternatives. A lot of research in this area needs to be done to make the right call, but considering that we absolutely want to keep TypeScript for type-checking, IDE/Language Service support, etc, it might make a lot of sense to stick with it and find ways to make it fast enough.
- Once the compiler supports localized compilation, we'd need to build plugins for [esbuild](https://esbuild.github.io/) or its alternative like [swc](https://swc.rs/).
- Angular CLI's build pipeline would have to be revamped to support this processing model. We could even consider adopting [Vite](https://vitejs.dev/) since they've done a lot of awesome work already 👍🏻.
- The impact on this change on other parts of Angular, like the language-service, google3 integration, and others is less clear at the moment, and will need to be researched.


## Trade offs

- Switching to transpilation represents a radical shift for the design of both the Angular compiler and runtime, and has an impact on how type-checking should work. All of this represents a significant effort, which would take time.


## Web ecosystem compatibility & Prior art

All of the following use transpilation or localized compilation approach:
- [JSX](https://facebook.github.io/jsx/)
- [lit](https://lit.dev/)
- [Vue](https://vuejs.org/)
- [Svelte](https://svelte.dev/)

## What's the goal of this issue?

The goal is to write down some of the ideas that have been made possible thanks to Ivy and start collecting early feedback that could be used as an input for future RFC.

## Alternatives considered

- We could switch over to an existing templating solution that is transpilable (JSX, lit), but these systems have fundamentally different component composition & change detection models, which would result in a major breaking change and regressions in runtime performance in some scenarios (due to our inability to perform certain optimizations). This change would not be worth the trouble.

- We could modify the template syntax to make it more suitable for purely syntactic transpilation (for example by removing selector matching)— while this might be worth doing in the future (pending more exploration of costs vs benefits), we can achieve most of the goals of this proposal by changing how Angular works internally while preserving backwards compatibility for most of the code out there and the investment into these code bases.