Skip to content

Instantly share code, notes, and snippets.

@alxhub
Last active May 16, 2018 19:40
Show Gist options
  • Save alxhub/0b40dcbce986c7df5b8d365c60f65a3c to your computer and use it in GitHub Desktop.
Save alxhub/0b40dcbce986c7df5b8d365c60f65a3c to your computer and use it in GitHub Desktop.

Problem

Developing Ivy requires being able to compile the same framework code, examples, tests, etc. using the legacy pipeline (ngc, view engine, etc) and using one of several new Ivy pipelines. Eventually, too, we want to start testing Ivy in g3, via a multi-phase rollout.

Development Requirements

We have several different kinds of code, both in the Angular repository and in others (e.g. CLI). In developing Ivy, we need to be able to test this code against the new compiler(s) and runtime, while continuing to support development of the existing Angular.

Types of code include:

  • Framework packages (core, common, router, etc).
  • Core framework tests
  • Documentation examples & tests
  • Example applications (Hello World, TODO, etc)
  • Downstream libraries that we want to test (Material)

The JIT disparity

In the legacy environment (View Engine), the decision of whether to run code under JIT or AOT is a runtime decision. By calling either the platformBrowserDynamic or platformBrowser API, either JIT or AOT mode will be utilized. The compiled code includes decorator information downleveled to annotations, which supports either case.

Libraries (such as common) are compiled with ngc internally in the ng_package rule, and published to NPM with enough information to run in either JIT or AOT mode, as determined by the application at runtime. In an Ivy environment, a library must decide at build time whether it wants to be AOT compiled, or preserve decorator information (which will trigger JIT compilation of the library at runtime). This causes issues.

The Google3 plan

We want to eventually start testing Ivy in google3. The rollout plan has two distinct phases:

Rollout Phase 1: ngc

In this phase, ngc runs using the same ng_module and summary-based metadata system as the legacy compiler. It generates Ivy .js code as well as .ngfactory.js shims which can be used with the existing bootstrap API.

Activating this phase allows us to test the Ivy runtime and individual decorator compilation in g3. It's activated by setting enableIvy to true in the angularCompilerOptions section of tsconfig.json.

Rollout Phase 2: ngtsc

In this phase, the new ngtsc compiler is used as a whole, instead of the ngc global analysis based compiler. This gets rid of the global analysis pipeline and all Angular-specific metadata formats (summaries, factories, etc). Dependency between compilation units now rely solely on .d.ts file information.

Activating this phase allows us to test our entire new compiler/metadata pipeline, with full locality, in g3. It's activated by setting enableIvy to "ngtsc" in angularCompilerOptions.

Requirements as seen by Bazel Rules

Given an Angular compilation unit (TS Program), then, we need to be able to compile it in 4 ways:

  • Via ngc legacy compilation, to support continued development of pre-Ivy Angular.
  • As a pure ts_library with no AOT compilation, to enable testing of JIT.
  • With ngc in Ivy mode, as required by Google3 phase 1.
  • With ngc in ngtsc mode, as required by Google3 phase 2.

We want to be able to run our tests in all 4 of these modes.

Test complications

Some tests will pass in certain modes but not in others. We need a plan for how to exclude specific tests from specific modes.

Material

Eventually, we want to test Material using Ivy, which (as Material uses Bazel) faces a similar set of challenges.

Potential Solutions

--define=ivy

In this proposal, Bazel's --define flag is used to modify the behavior of ngc and the ng_module rule.

  • With --define=ivy=false, the legacy pipeline runs.
  • With --define=ivy=jit, the ng_module rule behaves like ts_library.
  • With --define=ivy=global, the ng_module rule invokes ngc in global analysis mode (as in g3 phase 1)
  • With --define=ivy=local, the ng_module rule invokes ngc in ngtsc mode (as in g3 phase 2).

The actual mechanism of switching behavior could be left to ngc (for example, ngc could pretend to be tsc if it detects ivy=jit. However, Bazel rules need to declare their outputs, so the ng_module rule must be aware of whether generated files (e.g. summaries & factories) will be produced in whatever mode is being executed.

Material

If Material were converted to depend on Angular via a Bazel source dependency instead of via NPM, it could benefit from the --define=ivy flag in the same way.

Branches

We could have a Git branch for each mode above, and change the BUILD.bazel rules or ng_module implementation in each branch to build things accordingly. Ivy code would have to be synced between the branches.

@mhevery
Copy link

mhevery commented May 16, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment