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

platform-server errors with ivy-ngcc - UMD module - Angular 9.0.0-rc.7 #34544

Closed
naveedahmed1 opened this issue Dec 23, 2019 · 27 comments
Closed
Assignees
Labels
freq2: medium regression Indicates than the issue relates to something that worked in a previous version state: has PR type: bug/fix
Milestone

Comments

@naveedahmed1
Copy link
Contributor

🐞 bug report

Affected Package

The issue is caused by package @angular/platform-server

Is this a regression?

Yes, the previous version in which this bug was not present was: @angular/platform-server@9.0.0-rc.6

Description

When trying to compile my application with Ivy, I get errors on ivy ngcc for platform-server when compiling for umd bundles (for SSR)

🔬 Minimal Reproduction

Update any project to latest version of Angular (9.0.0-rc.7).

Add following config to angular.json:

"server": {
          "builder": "@angular-devkit/build-angular:server",
          "options": {
            "outputPath": "dist-server",
            "main": "src/main.server.ts",
            "tsConfig": "src/tsconfig.server.json"
          },
          "configurations": {
            "production": {
              "optimization": true,
              "outputHashing": "media",
              "sourceMap": false,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "bundleDependencies": "all",
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ]
            }
          }
        }

Then run command:

ng run MyProject:server:production

🔥 Exception or Error


Compiling @angular/platform-server : main as umd
Hash: f0b9625353a4d2f5af81
Time: 12116ms
Built at: 12/23/2019 8:02:36 PM
  Asset      Size  Chunks  Chunk Names
main.js  1.75 KiB       0  main
Entrypoint main = main.js
chunk    {0} main.js (main) 28 bytes [entry] [rendered]

ERROR in Expected UMD module file (/node_modules/url/node_modules/punycode/punycode.js) to contain exactly one statement, but found [object Object],[object Object].

🌍 Your Environment

Angular Version:


Angular CLI: 9.0.0-rc.7
Node: 12.13.1
OS: win32 x64

Angular: 9.0.0-rc.7
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... platform-server, router, service-worker
Ivy Workspace: Yes

Package                                    Version
--------------------------------------------------------------------
@angular-devkit/architect                  0.900.0-rc.7
@angular-devkit/build-angular              0.900.0-rc.7
@angular-devkit/build-optimizer            0.900.0-rc.7
@angular-devkit/build-webpack              0.900.0-rc.7
@angular-devkit/core                       9.0.0-rc.7
@angular-devkit/schematics                 9.0.0-rc.7
@angular/cdk                               9.0.0-rc.5
@angular/fire                              5.2.1
@angular/google-maps                       9.0.0-rc.5
@angular/material                          9.0.0-rc.5
@angular/pwa                               0.900.0-rc.7
@ngtools/webpack                           9.0.0-rc.7
@nguniversal/module-map-ngfactory-loader   9.0.0-next.9
@schematics/angular                        9.0.0-rc.7
@schematics/update                         0.900.0-rc.7
rxjs                                       6.5.3
typescript                                 3.6.4
webpack                                    4.41.2
@ngbot ngbot bot added this to the needsTriage milestone Dec 23, 2019
@naveedahmed1
Copy link
Contributor Author

@petebacondarwin @kara I am not sure but I believe it is similar to #31069

@gkalpak gkalpak self-assigned this Dec 23, 2019
@gkalpak
Copy link
Member

gkalpak commented Dec 23, 2019

@naveedahmed1, I cannot reproduce the issue. Here is what I tried:

# Attempt 1
npm install --global @angular/cli@9.0.0-rc.7
ng new test-app --defaults
cd test-app
ng add @nguniversal/express-engine --client-project test-app
ng run test-app:server:production

# Attempt 2
rm -rf node_modules
npm install
# Copied your config from https://github.com/angular/angular/issues/34544#issue-541795169 into `angular.json`
ng run test-app:server:production

# Attempt 3
./node_modules/.bin/ngcc

In all cases above, the commands completed successfully and in the last one @angular/platform-server was compiled as UMD (saw Compiling @angular/platform-server : main as umd in the logs).

Can you, please, provide a minimal reproduction (e.g. a project we can check out and run) with specific instructions on how to reproduce the problem?

@naveedahmed1
Copy link
Contributor Author

@gkalpak I have added you to a private repo and dropped you an email.

@gkalpak
Copy link
Member

gkalpak commented Dec 23, 2019

Thx, @naveedahmed1. I took a look and there are actually two issues involved:

  1. @angular/platform-server imports Node.js' built-in url module here. ngcc fails to recognize that this is the Node.js built-in and tries to process url package (which is a transitive dependency of the project and ends up in top-level node_modules/ via npm deduping).

  2. The url package dependes on the punycode package, whose main file is in the form ;(function(root) { ... }(this)); (which is neither CommonJS nor UMD). ngcc assumes that the file pointed to by a package.json's main property will be in either CommonJS or UMD format. Given that punycode.js does not look like CommonJS, ngcc tries to parse it as UMD and it expects UMD files to be in format (function (factory) { ... })(function (...) { ... }); (and thus only have one top-level statement). However, the file has two top-level statements (one empty statement, followed by a parenthesized function call): ;(function(root) { ... }(this));

Having 100% static evaluation for the UMD format is probably out of scope for ngcc (as it would be quite complex/costly with all the different variations), so we have to rely on heuristics (which can't be 100% accurate). Off the top of my head, here are some things we can improve:

  1. Teach ngcc to ignore Node.js built-in modules as dependencies.
  2. Do not assume that package.json > main points to either CommonJS or UMD. Improve our detection of the format main files and throw a more descriptive error for unsupported formats.

@naveedahmed1
Copy link
Contributor Author

naveedahmed1 commented Dec 23, 2019

Thank you so much @gkalpak for sharing the details. Let me also share that it works fine with Angular 9.0.0-rc.6 so if you could please also take a look at what exactly has changed in Angular 9.0.0-rc.7 that causes ngcc to throw this error.

@petebacondarwin
Copy link
Member

@tayambamwanza
Copy link

Can confirm also experiencing this issue only from Angular 9.0.0-rc.7, did not exist in Angular 9.0.0-rc.6

@Gbuomprisco

This comment has been minimized.

@naveedahmed1
Copy link
Contributor Author

It seems that this issue is caused by the recent changes related to UMD bundles in Angular 9.0.0-rc.7

#34356

84a7d8a

c26738d

@gkalpak

This comment has been minimized.

@Gbuomprisco

This comment has been minimized.

@gkalpak

This comment has been minimized.

@naveedahmed1
Copy link
Contributor Author

I'm still having this issue with latest Angular 9.0.0-rc.8.

@kainiedziela
Copy link

kainiedziela commented Jan 16, 2020

Issue not solved with Angular 9.0.0-rc.9.

gkalpak added a commit to gkalpak/angular that referenced this issue Jan 16, 2020
Previously, while trying to build an `NgccReflectionHost`'s
`privateDtsDeclarationMap`, `computePrivateDtsDeclarationMap()` would
try to collect exported declarations from all source files of the
program (i.e. without checking whether they were within the target
entry-point, as happens for declarations in `.d.ts` files).

Most of the time, that would not be a problem, because external packages
would be represented as `.d.ts` files in the program. But when an
external package had no typings, the JS files would be used instead. As
a result, the `ReflectionHost` would try to (unnecessarilly) parse the
file to extract exported declarations, which again would be harmless in
most cases.

There are certain cases, though, where the `ReflectionHost` would throw
an error, because it could not parse the external package's JS file.
This could happen, for example, in `UmdReflectionHost`, which expects
the file to contain exactly one statement. See angular#34544 for more details
on a real-world failure.

This commit fixes the issue by ensuring that
`computePrivateDtsDeclarationMap()` will only collect declarations from
files within the target entry-point.

Jira issue: [FW-1794](https://angular-team.atlassian.net/browse/FW-1794)

Fixes angular#34544
gkalpak added a commit to gkalpak/angular that referenced this issue Jan 16, 2020
Previously, while trying to build an `NgccReflectionHost`'s
`privateDtsDeclarationMap`, `computePrivateDtsDeclarationMap()` would
try to collect exported declarations from all source files of the
program (i.e. without checking whether they were within the target
entry-point, as happens for declarations in `.d.ts` files).

Most of the time, that would not be a problem, because external packages
would be represented as `.d.ts` files in the program. But when an
external package had no typings, the JS files would be used instead. As
a result, the `ReflectionHost` would try to (unnecessarilly) parse the
file in order to extract exported declarations, which in turn would be
harmless in most cases.

There are certain cases, though, where the `ReflectionHost` would throw
an error, because it cannot parse the external package's JS file. This
could happen, for example, in `UmdReflectionHost`, which expects the
file to contain exactly one statement. See angular#34544 for more details on a
real-world failure.

This commit fixes the issue by ensuring that
`computePrivateDtsDeclarationMap()` will only collect exported
declarations from files within the target entry-point.

Jira issue: [FW-1794](https://angular-team.atlassian.net/browse/FW-1794)

Fixes angular#34544
@gkalpak
Copy link
Member

gkalpak commented Jan 16, 2020

@naveedahmed1, @kainiedziela (or anyone else having the same issue): Could you try with the build artifacts from #34811 and see if the problem is fixed for you?

@naveedahmed1
Copy link
Contributor Author

@gkalpak sure I can try that can you please guide how to use it?

BTW I also added you to a private repository, if you could please use that to test it? Use npm run build:ssr to reproduce the error.

@gkalpak
Copy link
Member

gkalpak commented Jan 17, 2020

sure I can try that can you please guide how to use it?

You can find instructions on how to use them here. Basically, you just replace the versions in your package.json to point to the artifacts URL.

BTW I also added you to a private repository, if you could please use that to test it? Use npm run build:ssr to reproduce the error.

I have done that already and the error goes away. But I want to verify that everything still works as expected at runtime and I am not sure how to do that for your app.

@naveedahmed1
Copy link
Contributor Author

@gkalpak I tried it and its throwing below error:

An unhandled exception occurred: compiler_1.Version is not a constructor
See "C:\Users\NAVEED~1\AppData\Local\Temp\ng-rz0OsH\angular-errors.log" for further details.

I am using below packages:

  "dependencies": {
    "@angular/animations": "https://589268-24195339-gh.circle-artifacts.com/0/angular/animations-pr34811-38e9d9ef1a.tgz",
    "@angular/cdk": "9.0.0-rc.5",
    "@angular/common": "https://589268-24195339-gh.circle-artifacts.com/0/angular/common-pr34811-38e9d9ef1a.tgz",
    "@angular/compiler": "https://589268-24195339-gh.circle-artifacts.com/0/angular/compiler-cli-pr34811-38e9d9ef1a.tgz",
    "@angular/core": "https://589268-24195339-gh.circle-artifacts.com/0/angular/core-pr34811-38e9d9ef1a.tgz",
    "@angular/fire": "5.2.1",
    "@angular/forms": "https://589268-24195339-gh.circle-artifacts.com/0/angular/forms-pr34811-38e9d9ef1a.tgz",
    "@angular/google-maps": "9.0.0-rc.5",
    "@angular/material": "9.0.0-rc.5",
    "@angular/platform-browser": "https://589268-24195339-gh.circle-artifacts.com/0/angular/platform-browser-pr34811-38e9d9ef1a.tgz",
    "@angular/platform-browser-dynamic": "https://589268-24195339-gh.circle-artifacts.com/0/angular/platform-browser-dynamic-pr34811-38e9d9ef1a.tgz",
    "@angular/platform-server": "https://589268-24195339-gh.circle-artifacts.com/0/angular/platform-server-pr34811-38e9d9ef1a.tgz",
    "@angular/pwa": "0.900.0-rc.6",
    "@angular/router": "https://589268-24195339-gh.circle-artifacts.com/0/angular/router-pr34811-38e9d9ef1a.tgz",
    "@angular/service-worker": "https://589268-24195339-gh.circle-artifacts.com/0/angular/service-worker-pr34811-38e9d9ef1a.tgz",
    "@nguniversal/module-map-ngfactory-loader": "9.0.0-next.9",

  "devDependencies": {
    "@angular-builders/custom-webpack": "8.4.1",
    "@angular-devkit/build-angular": "^0.900.0-rc.9",
    "@angular/cli": "^9.0.0-rc.7",
    "@angular/compiler-cli": "https://589268-24195339-gh.circle-artifacts.com/0/angular/compiler-cli-pr34811-38e9d9ef1a.tgz",
    "@angular/language-service": "https://589268-24195339-gh.circle-artifacts.com/0/angular/language-service-pr34811-38e9d9ef1a.tgz",

@petebacondarwin
Copy link
Member

This is your problem @naveedahmed1 :

"@angular/compiler": "https://589268-24195339-gh.circle-artifacts.com/0/angular/compiler-cli-pr34811-38e9d9ef1a.tgz",

Notice that the URL refers to compiler-cli.

@naveedahmed1
Copy link
Contributor Author

Thank you so much @petebacondarwin :)

I have done that already and the error goes away. But I want to verify that everything still works as expected at runtime and I am not sure how to do that for your app.

@gkalpak yes the backend is in .Net and that's a separate repo. I tested it on my side and I can confirm that the issue has been resolved on runtime as well. Thank you so much for the quick fix :)

Looking forward to have it in next release.

gkalpak added a commit to gkalpak/angular that referenced this issue Jan 18, 2020
Previously, while trying to build an `NgccReflectionHost`'s
`privateDtsDeclarationMap`, `computePrivateDtsDeclarationMap()` would
try to collect exported declarations from all source files of the
program (i.e. without checking whether they were within the target
package, as happens for declarations in `.d.ts` files).

Most of the time, that would not be a problem, because external packages
would be represented as `.d.ts` files in the program. But when an
external package had no typings, the JS files would be used instead. As
a result, the `ReflectionHost` would try to (unnecessarilly) parse the
file in order to extract exported declarations, which in turn would be
harmless in most cases.

There are certain cases, though, where the `ReflectionHost` would throw
an error, because it cannot parse the external package's JS file. This
could happen, for example, in `UmdReflectionHost`, which expects the
file to contain exactly one statement. See angular#34544 for more details on a
real-world failure.

This commit fixes the issue by ensuring that
`computePrivateDtsDeclarationMap()` will only collect exported
declarations from files within the target package.

Jira issue: [FW-1794](https://angular-team.atlassian.net/browse/FW-1794)

Fixes angular#34544
@naveedahmed1
Copy link
Contributor Author

I'm curious to know - is @angular/fire with bundleDependencies all working?

@Gbuomprisco it was working fine with Angular 9.0.0-rc.6 and earlier. Hopefully @gkalpak's recent commit (gkalpak@8e53a2b) will fix this in next release.

@fergalmoran
Copy link

Does anyone know if this commit made it into RC10? It's a bit painful having to use the build artifacts.

@gkalpak
Copy link
Member

gkalpak commented Jan 22, 2020

No, the fix hasn't landed yet. This is the PR (which is still open): #34811

AndrewKushnir pushed a commit that referenced this issue Jan 23, 2020
…#34811)

Previously, while trying to build an `NgccReflectionHost`'s
`privateDtsDeclarationMap`, `computePrivateDtsDeclarationMap()` would
try to collect exported declarations from all source files of the
program (i.e. without checking whether they were within the target
package, as happens for declarations in `.d.ts` files).

Most of the time, that would not be a problem, because external packages
would be represented as `.d.ts` files in the program. But when an
external package had no typings, the JS files would be used instead. As
a result, the `ReflectionHost` would try to (unnecessarilly) parse the
file in order to extract exported declarations, which in turn would be
harmless in most cases.

There are certain cases, though, where the `ReflectionHost` would throw
an error, because it cannot parse the external package's JS file. This
could happen, for example, in `UmdReflectionHost`, which expects the
file to contain exactly one statement. See #34544 for more details on a
real-world failure.

This commit fixes the issue by ensuring that
`computePrivateDtsDeclarationMap()` will only collect exported
declarations from files within the target package.

Jira issue: [FW-1794](https://angular-team.atlassian.net/browse/FW-1794)

Fixes #34544

PR Close #34811
@naveedahmed1
Copy link
Contributor Author

@AndrewKushnir can you please confirm if its fixed in RC 11?

@gkalpak
Copy link
Member

gkalpak commented Jan 27, 2020

Yes, the fix is included in v9.0.0-rc.11.

@naveedahmed1
Copy link
Contributor Author

Thank you so much @gkalpak for the confirmation :)

@kara kara added regression Indicates than the issue relates to something that worked in a previous version and removed severity5: ivy-compat labels Feb 11, 2020
sonukapoor pushed a commit to sonukapoor/angular that referenced this issue Feb 13, 2020
…angular#34811)

Previously, while trying to build an `NgccReflectionHost`'s
`privateDtsDeclarationMap`, `computePrivateDtsDeclarationMap()` would
try to collect exported declarations from all source files of the
program (i.e. without checking whether they were within the target
package, as happens for declarations in `.d.ts` files).

Most of the time, that would not be a problem, because external packages
would be represented as `.d.ts` files in the program. But when an
external package had no typings, the JS files would be used instead. As
a result, the `ReflectionHost` would try to (unnecessarilly) parse the
file in order to extract exported declarations, which in turn would be
harmless in most cases.

There are certain cases, though, where the `ReflectionHost` would throw
an error, because it cannot parse the external package's JS file. This
could happen, for example, in `UmdReflectionHost`, which expects the
file to contain exactly one statement. See angular#34544 for more details on a
real-world failure.

This commit fixes the issue by ensuring that
`computePrivateDtsDeclarationMap()` will only collect exported
declarations from files within the target package.

Jira issue: [FW-1794](https://angular-team.atlassian.net/browse/FW-1794)

Fixes angular#34544

PR Close angular#34811
@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 Mar 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
freq2: medium regression Indicates than the issue relates to something that worked in a previous version state: has PR type: bug/fix
Projects
None yet
Development

Successfully merging a pull request may close this issue.