Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to disable sub entry points #1758

Open
victorsc opened this issue Sep 28, 2020 · 8 comments
Open

Ability to disable sub entry points #1758

victorsc opened this issue Sep 28, 2020 · 8 comments

Comments

@victorsc
Copy link

Type of Issue

[ ] Bug Report
[x] Feature Request

Description

As a library developer, I would like to have the possibility not to build sub entry points (for dev builds).

Details

We are experiencing build performance issues with our Angular library (30+ sub entries) even after migrating to Angular 10 (related to #1222).

lib build time (seconds) ng 8 non-Ivy (ng 10)
with sub-entries 194 90.93
without sub-entries 36 32.08

This is why we decided to have 2 separate builds:

  • a production one with sub-entries so that the library is tree-shaked
  • a development one without sub-entries - anindex.dev.ts barrel that exports the sub-entries.

In order allow both builds without chaing the code, we created a custom Angular builder that:

  1. generates package.json files for each sub-entry
  2. builds
  3. cleans-up previously generated package.json file.

Expected Behaviour

I would like to have a configuration flag so that ng-packagr ignores sub-entries. This way we can run ng-packagr for the dev build without the pre/post build processing.

Version Information

$ node_modules/.bin/ng-packagr --version
ng-packagr: 10.1.0
@angular/compiler: 10.0.14
typescript: 3.9.7
rxjs: 6.6.3
node: 12.13.1
yarn: 1.21.1
@SchnWalter
Copy link
Contributor

Interesting find. If what you are trying to solve is a performance problem, the approach is not to ignore sub-entry points, because you will run into issues with the dependency graph. You should provide a reproduction repository with generated code where this difference in performance is visible, maybe the overhead of entry points could be reduced.

@victorsc victorsc changed the title Ability to ignore sub entry points Ability to disable sub entry points Sep 30, 2020
@victorsc
Copy link
Author

Hi @SchnWalter

I generated a skeleton library and added 50 modules.

yarn && yarn run build // build time ~ 8 seconds
git checkout sub-entries && yarn run build // build time ~47 seconds

@SchnWalter
Copy link
Contributor

SchnWalter commented Sep 30, 2020

From what I can tell, scheduleEntryPoints is creating a lot of class instances for each entry point. We might be able to reduce the resource usage and the build duration by reusing some of the instances, but this will be tricky when it comes to external packages like the mainNgcc process from @angular/compiler-cli/ngcc:

mainNgcc({
basePath: this._nodeModulesDirectory,
targetEntryPointPath: path.dirname(packageJsonPath),
compileAllFormats: false,
propertiesToConsider: ['es2015', 'browser', 'module', 'main'],
createNewEntryPointFormats: true,
logger: this._logger,
tsConfigPath: this.projectPath,
});

For any change, we'll need to make sure that we don't introduce regressions and we'll need to start adding benchmarks and tests. And we'll need to check with the Angular Core team if the ngcc process can be reused, it probably can, because we have support for live-reload.

@JoostK
Copy link
Member

JoostK commented Oct 10, 2020

@victorsc I looked into a profiler trace for your reproduction and one thing stood out: TypeScript type checking was taking ~35s of a total of ~50s. The reason is that the tsconfig.lib.json does not specify "skipLibCheck": true and that is not configured by default in ng-packagr, so all entry-points pay the cost of type-checking the .d.ts files of included libraries and default libraries. This adds a huuuuuuge overhead to processing the packages; setting that flag reduces the execution from ~50s to ~18s and significantly drops retained memory when used with the --watch flag from ~1030MB to just ~255MB.

@SchnWalter ngcc is already somewhat optimized to be smart about whether it needs to run or not, but it still does add some overhead. I'm seeing about 4s being in spent in ngcc in total in the above reproduction, just under 100ms per entry-point. Although that is noticeable, it's also not the end of the world. I think we can do something to reduce the overhead per entry-point to almost nil, though, if ng-packagr would maintain a shared cache of which modules have been processed.

I have incorporated the above changes and some more improvements in #1764 which reduces the total time spent for @victorsc's repro from ~50s to just ~12s. Note that the repro does not represent a real-world scenario; as all entry-points are very small. It does show however that the overhead of an entry-point is significantly reduced.

@JoostK
Copy link
Member

JoostK commented Oct 10, 2020

I briefly talked to @alan-agius4 and he rightfully mentioned that skipLibCheck will also disabled type-checking of local .d.ts files, which is not something we want to do by default. That means that you'll only get the largest perf improvement if you configure it yourself.

@alan-agius4
Copy link
Member

I think on future we might consider building all the entry points with a single TS program.

The only problem that we need to overcome is rootDirs, which at the moment we set so users don’t accidentally, reference entry-points using relative paths.

@SchnWalter
Copy link
Contributor

Thanks @JoostK. Nice work! The build time for a basic library[1] is down to ~18% of what I saw with the latest version of the master branch. About ~13s instead of ~72s

@victorsc, in my last comment I forgot to mention that in the sub-entries branch of your example library you are actually building all the files 3 times: the first time in the package root, then once more in a /lib sub package and one last time in the sub package containing the module.


[1] a generated library that included a basic component and a basic service in each of the 90 sub packages

@JoostK
Copy link
Member

JoostK commented Oct 13, 2020

The change to enable skipLibCheck by default has been retracted from #1764. It's not universally safe as it also causes local declaration files not to be checked.

For projects with a lot of entry-points where the performance penalty is deemed unacceptable it is possible to enable the "skipLibCheck" flag in tsconfig.lib.json.

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

No branches or pull requests

4 participants