https://github.com/angular/angular
Revision 016a41b14d3703ef885e7faaa8698d7772f376a6 authored by Doug Parker on 01 August 2020, 00:42:21 UTC, committed by Andrew Kushnir on 06 August 2020, 16:02:17 UTC
Roll forward of #38147.

This allows Closure compiler to tree shake unused constructor calls to `NgModuleFactory`, which is otherwise considered
side-effectful. The Angular compiler generates factory objects which are exported but typically not used, as they are
only needed for compatibility with View Engine. This results in top-level constructor calls, such as:

```typescript
export const FooNgFactory = new NgModuleFactory(Foo);
```

`NgModuleFactory` has a side-effecting constructor, so this statement cannot be tree shaken, even if `FooNgFactory` is
never imported. The `NgModuleFactory` continues to reference its associated `NgModule` and prevents the module and all
its unused dependencies from being tree shaken, making Closure builds significantly larger than necessary.

The fix here is to wrap `NgModuleFactory` constructor with `noSideEffects(() => /* ... */)`, which tricks the Closure
compiler into assuming that the invoked function has no side effects. This allows it to tree-shake unused
`NgModuleFactory()` constructors when they aren't imported. Since the factory can be removed, the module can also be
removed (if nothing else references it), thus tree shaking unused dependencies as expected.

The one notable edge case is for lazy loaded modules. Internally, lazy loading is done as a side effect when the lazy
script is evaluated. For Angular, this side effect is registering the `NgModule`. In Ivy this is done by the
`NgModuleFactory` constructor, so lazy loaded modules **cannot** have their top-level `NgModuleFactory` constructor
call tree shaken. We handle this case by looking for the `id` field on `@NgModule` annotations. All lazy loaded modules
include an `id`. When this `id` is found, the `NgModuleFactory` is generated **without** with `noSideEffects()` call,
so Closure will not tree shake it and the module will lazy-load correctly.

PR Close #38320
1 parent 7a527b4
History
Tip revision: 016a41b14d3703ef885e7faaa8698d7772f376a6 authored by Doug Parker on 01 August 2020, 00:42:21 UTC
fix(compiler-cli): mark eager `NgModuleFactory` construction as not side effectful (#38320)
Tip revision: 016a41b
File Mode Size
.circleci
.devcontainer
.github
.ng-dev
.vscode
.yarn
aio
dev-infra
docs
goldens
integration
modules
packages
scripts
third_party
tools
.bazelignore -rw-r--r-- 4.3 KB
.bazelrc -rw-r--r-- 6.2 KB
.bazelversion -rw-r--r-- 213 bytes
.clang-format -rw-r--r-- 73 bytes
.editorconfig -rw-r--r-- 245 bytes
.gitattributes -rw-r--r-- 314 bytes
.gitignore -rw-r--r-- 726 bytes
.gitmessage -rw-r--r-- 7.2 KB
.mailmap -rw-r--r-- 51 bytes
.nvmrc -rw-r--r-- 8 bytes
.pullapprove.yml -rw-r--r-- 44.1 KB
.yarnrc -rw-r--r-- 128 bytes
BUILD.bazel -rw-r--r-- 1.7 KB
CHANGELOG.md -rw-r--r-- 719.8 KB
CODE_OF_CONDUCT.md -rw-r--r-- 1.1 KB
CONTRIBUTING.md -rw-r--r-- 14.2 KB
LICENSE -rw-r--r-- 1.1 KB
README.md -rw-r--r-- 1.2 KB
WORKSPACE -rw-r--r-- 4.3 KB
browser-providers.conf.js -rw-r--r-- 8.9 KB
gulpfile.js -rw-r--r-- 1.2 KB
karma-js.conf.js -rw-r--r-- 7.6 KB
package.json -rw-r--r-- 8.3 KB
test-events.js -rw-r--r-- 259 bytes
test-main.js -rw-r--r-- 11.3 KB
tslint.json -rw-r--r-- 2.3 KB
yarn.lock -rw-r--r-- 676.1 KB
yarn.lock.readme.md -rw-r--r-- 1.3 KB

README.md

back to top