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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

NGCC crashes with "RangeError: Maximum call stack size exceeded" on umd compilation of library #41509

Closed
jgbpercy opened this issue Apr 8, 2021 · 11 comments
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Milestone

Comments

@jgbpercy
Copy link

jgbpercy commented Apr 8, 2021

馃悶 bug report

Affected Package

The issue is caused by package @angular/compiler-cli (I think?)

Is this a regression?

No

Description

When NGCC tries to compile our internal library as UMD, we get RangeError: Maximum call stack size exceeded.

This library has been in use since v9 and goes through NGCC fine as ESM - we use it in several live Ivy applications.

However, I believe the Ivy language service tries to compile using UMD, as does Nx when we try to add apps that use this lib to an Nx workspace (currently that workspace doesn't contain the library code itself).

Our assumption is that there's almost certainly something wrong (maybe something very obviously wrong!) with our lib that's causing this, but we have no idea how to determine what that is from the error we're getting. I'll be honest and say I don't really understand UMD or JS module systems other than ESM, or when and why a UMD compilation is needed. We've tried what we can think of to fix this but we're now stuck.

馃敩 Minimal Reproduction

This is in private code and I have no idea how to create a minimal repro, but I can share access to a private GitHub repository - just let me know who to share with.

After cloning the repo and installing deps, the easy way to reproduce is:

npm run prodCheckBuild

then

node node_modules/@angular/compiler-cli/ngcc/main-ngcc --source node_modules/@capp/angular

馃敟 Exception or Error

The call stack varies, but it most commonly looks like this after repeated attempts. It always contains UmdReflectionHost calls.


Compiling @capp/angular : main as umd
Error: Error on worker #2: RangeError: Maximum call stack size exceeded
    at resolveNameHelper (C:\Source\CAPP.SharedAngular\node_modules\typescript\lib\typescript.js:43778:35)
    at resolveName (C:\Source\CAPP.SharedAngular\node_modules\typescript\lib\typescript.js:43776:20)
    at resolveEntityName (C:\Source\CAPP.SharedAngular\node_modules\typescript\lib\typescript.js:44999:42)
    at getSymbolOfNameOrPropertyAccessExpression (C:\Source\CAPP.SharedAngular\node_modules\typescript\lib\typescript.js:75600:28)
    at getSymbolAtLocation (C:\Source\CAPP.SharedAngular\node_modules\typescript\lib\typescript.js:75665:28)
    at Object.getSymbolAtLocation (C:\Source\CAPP.SharedAngular\node_modules\typescript\lib\typescript.js:42656:31)
    at UmdReflectionHost.findUmdImportParameter (C:\Source\CAPP.SharedAngular\node_modules\@angular\compiler-cli\ngcc\src\host\umd_host.js:341:45)
    at UmdReflectionHost.getImportPathFromParameter (C:\Source\CAPP.SharedAngular\node_modules\@angular\compiler-cli\ngcc\src\host\umd_host.js:424:40)
    at UmdReflectionHost.getUmdModuleDeclaration (C:\Source\CAPP.SharedAngular\node_modules\@angular\compiler-cli\ngcc\src\host\umd_host.js:412:35)
    at UmdReflectionHost.getDeclarationOfIdentifier (C:\Source\CAPP.SharedAngular\node_modules\@angular\compiler-cli\ngcc\src\host\umd_host.js:54:70)
    at ClusterMaster.onWorkerMessage (C:\Source\CAPP.SharedAngular\node_modules\@angular\compiler-cli\ngcc\src\execution\cluster\master.js:195:27)
    at C:\Source\CAPP.SharedAngular\node_modules\@angular\compiler-cli\ngcc\src\execution\cluster\master.js:55:95
    at ClusterMaster. (C:\Source\CAPP.SharedAngular\node_modules\@angular\compiler-cli\ngcc\src\execution\cluster\master.js:293:57)
    at step (C:\Source\CAPP.SharedAngular\node_modules\tslib\tslib.js:143:27)
    at Object.next (C:\Source\CAPP.SharedAngular\node_modules\tslib\tslib.js:124:57)
    at C:\Source\CAPP.SharedAngular\node_modules\tslib\tslib.js:117:75
    at new Promise ()
    at Object.__awaiter (C:\Source\CAPP.SharedAngular\node_modules\tslib\tslib.js:113:16)
    at EventEmitter. (C:\Source\CAPP.SharedAngular\node_modules\@angular\compiler-cli\ngcc\src\execution\cluster\master.js:287:32)
    at EventEmitter.emit (events.js:315:20)

Assuming there is a genuine issue with our library code, I'd hope it might be possible to give a more helpful error?

馃實 Your Environment

Angular Version:


Angular CLI: 11.2.4
Node: 14.15.1
OS: win32 x64

Angular: 11.2.5
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1102.4
@angular-devkit/build-angular   0.1102.4
@angular-devkit/core            11.2.4
@angular-devkit/schematics      11.2.4
@angular/cdk                    11.2.4
@angular/cli                    11.2.4
@angular/flex-layout            11.0.0-beta.33
@schematics/angular             11.2.4
@schematics/update              0.1102.4
ng-packagr                      11.1.2
rxjs                            6.6.3
typescript                      4.0.5

Anything else relevant?

Windows 10

Unlikely to matter but we've yet to update to npm 7.

@ngbot ngbot bot added this to the needsTriage milestone Apr 8, 2021
@petebacondarwin
Copy link
Member

Can you work out if you actually use the UMD format of this package? There are only a few cases (Universal/online bundling) where it is needed. If not then you can simply configure your build to avoid UMD for this package.

@petebacondarwin
Copy link
Member

By the way, UMD is quite hard for ngcc to process. But it is nigh on impossible if the UMD is minified. So this might be the underlying cause of the stack overflow.

@jgbpercy
Copy link
Author

jgbpercy commented Apr 9, 2021

I'm almost certain we don't need it, and I looked for a way to disable it but I couldn't see one. I'm probably missed something really obvious! What I found was this ng-packagr issue that seemed to say that it's not possible with ng-packagr, and we don't want to move away from ng-packagr as it does everything else we need really well.

Apologies if I'm completely misunderstanding something here, and thanks for the help...

@JoostK
Copy link
Member

JoostK commented Apr 9, 2021

Are you using Jest? Jest uses the main property to load bundles, which are the UMD bundles.

The stacktrace makes me think this might be a bug in TypeScript. Maybe you could try with TS 4.1 (not 4.2, that is not yet supported in Angular 11).

@jgbpercy
Copy link
Author

jgbpercy commented Apr 9, 2021

TS 4.1 doesn't seem to make a difference.

The Nx workspace we're trying to set up would use Jest, although it seems from browsing this issue that there's at least a workaround for Jest using UMD, and possible Nx already achieves that (maybe I'm misunderstanding - only skim-read at that issue so far).

Certainly doesn't seem to be Jest that's causing the current UMD compilation... We're seeing it in the npm install hook from Nx, which as far as I understand blanket runs NGCC on all of your Angular packages, and when enabling the Ivy language service, which seems to do the same.

I hacked around in the built library code to delete the UMD files form /bundles, and point package.json "main" at "fesm2015/capp-angular.js" (same as "module"). NGCC runs ok on that and doesn't complain, so if that's the workaround for now I can put an extra script in our build to do that. As mentioned I don't really understand legacy JS module systems at all (usually Angular means I don't have to care about that stuff 馃槃), so I'm not sure what else that would break, if anything.

@petebacondarwin
Copy link
Member

I'm assuming that this @capp/angular is an internal private library?
Was it generated using ng-packagr? Does it have any other formats in it other than UMD?

The standard Angular CLI and Language Service integrations with ngcc should not try to compile UMD unless the application itself actually requires it.

When you say that ngcc is being run as part of the installation, do you have a postinstall script in your package.json that is running ngcc? If so, what are the command line arguments being passed to ngcc?

@jgbpercy
Copy link
Author

jgbpercy commented Apr 9, 2021

I'm assuming that this @capp/angular is an internal private library?

Yep

Was it generated using ng-packagr? Does it have any other formats in it other than UMD?

Yep it uses ng-packagr.

The build output looks like this, and the relevant bits of the lib's package.json:

  "main": "bundles/capp-angular.umd.js",
  "module": "fesm2015/capp-angular.js",
  "es2015": "fesm2015/capp-angular.js",
  "esm2015": "esm2015/capp-angular.js",
  "fesm2015": "fesm2015/capp-angular.js",
  "typings": "capp-angular.d.ts",
  "metadata": "capp-angular.metadata.json",

The extent of my knowledge is that the UMD build of the lib (i.e. the files in the bundles directory, which package.json "main" points at) is something ng-packagr does by default and/or has always done. As far as I know we've never done anything to enable that and my assumption was it was a standard thing.

However, the library is consumed through ESM in the apps that use it and that works fine - the lib is still early in development but we have some prod apps that use it without issue.

The standard Angular CLI and Language Service integrations with ngcc should not try to compile UMD unless the application itself actually requires it.

I don't know what to say - when we enable the Ivy language service in an app that consumes the library, we get the same error from the language service output, and the language service wont enable. This is despite the same app compiling and running absolutely fine using Ivy.

When you say that ngcc is being run as part of the installation, do you have a postinstall script in your package.json that is running ngcc? If so, what are the command line arguments being passed to ngcc?

We don't have our own postinstall script, no, this is something Nx does by default. It's just out of the box Nx config using the latest version of Nx and following these docs.

To be absolutely clear though, the error predates any attempt we've made to use Nx and occurs in codebases that have nothing to do with Nx and have no npm hooks whatsoever. I attempted to use the Ivy language server pretty soon after the flag was first available and got this error... At the time I filed it away as one to investigate and raise later if it didn't get resolved in later versions.

The error can also be repro-ed just with the library code by running ngcc on the built output, with just the --source arg pointing at the built output (neither Nx nor Jest are currently anywhere near that code).

@petebacondarwin
Copy link
Member

OK, so I am sure there is something skewy going on with Nx and/or language-server, here is the nuclear option. Add this to your project root:

ngcc.config.js

module.exports = {
  packages: {
    '@capp/angular': {
      entryPoints: {
        '.': { override: { main: undefined } },
      }
    }
  }
};

That should instruct ngcc to ignore (and not attempt to process) the UMD format for this package.
Be aware that if something actually relies upon this format of this package then it won't work and you might get weird and non-obvious errors. But given that it appears that ngcc is unable to process it anyway, right now, I don't think you will be in a worse position.

@jelbourn jelbourn added the P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent label Apr 9, 2021
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Apr 9, 2021
@jgbpercy
Copy link
Author

Just confirming that with this fix neither Nx nor the language service are complaining any longer. Obviously we may need to re-examine if we need UMD builds, but I don't think that will be the case for a long time, if ever.

Thanks v much for your help on this, really appreciated.

If you do want to investigate what's going on with this one in the future then I'm still happy to share code, but as far as being a blocker for us this is resolved. Will leave up to you whether to close the issue or leave open.

@petebacondarwin
Copy link
Member

Without access to the library, there is not much we can do to fix this. So I am going to close this.
If you get blocked again @jgbpercy - please open another issue.

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators May 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

No branches or pull requests

5 participants