Vscode-ng-language-service: Angular language service doesn't see components from library built with Ivy.

Created on 5 Dec 2019  ·  23Comments  ·  Source: angular/vscode-ng-language-service

🐞 bug report

Affected Package

The issue is caused by package @angular/language-service

Description

Angular language service doesn't see components from library built with Ivy.
Application is built correctly.

Error


'lib-component' is not a known element:
1. If 'lib-component' is an Angular component, then verify that it is part of this module.
2. If 'lib-component' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.ng(0)

Environment


Editor: VisualStudio Code
Editor extension: angular.ng-template v0.900.0

Angular CLI: 9.0.0-rc.5
Node: 10.17.0
OS: darwin x64

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

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.900.0-rc.5
@angular-devkit/build-angular      0.900.0-rc.5
@angular-devkit/build-ng-packagr   0.900.0-rc.5
@angular-devkit/build-optimizer    0.900.0-rc.5
@angular-devkit/build-webpack      0.900.0-rc.5
@angular-devkit/core               9.0.0-rc.5
@angular-devkit/schematics         9.0.0-rc.5
@angular/cdk                       9.0.0-rc.4
@ngtools/webpack                   9.0.0-rc.5
@schematics/angular                9.0.0-rc.5
@schematics/update                 0.900.0-rc.5
ng-packagr                         9.0.0-rc.3
rxjs                               6.5.3
typescript                         3.6.4
webpack                            4.41.2
bug ivy

Most helpful comment

Has any progress been made on this.

All 23 comments

Update. Ivy compiler doesn't create file lib-name.metadata.json in project_root/dist/lib-name.
Could this be the problem?

+1 I have the same issue

Post version 9, we are going to switch the language service internals to use the Ivy compiler. Until then, the language service would need to rely on metadata.json to retrieve additional information about a directive.

Yes this is the issue. To resolve for the time being, you will need to build the prod version of your library which has "enableIvy": false in tsconfig. This then generates the metadata file needed in the dist folder.

ie ng build lib-component --prod

But you also need to make sure to Restart Angular Language service after each build in vs-code.

All this information is not easily found between the vs-code plugin and angular itself. Just a heads up for anyone else experiencing this same issue.

My assumption that

@jiverson regarding your workaround ng build lib-component --prod for me yields an error An unhandled exception occurred: Configuration 'production' is not set in the workspace. and I've seen evidence elsewhere that the --prod flag for libraries is no longer relevant. I'm using @angular/cli v8.3.25 though... so while this issue has been referred to as a possible duplicate for #665, I'm not so sure it is. Any thoughts? /cc @ayazhafiz

Any updates on this? We have our own libraries developed and published in ivy even in prod.

Work is underway to move the language service to an Ivy backend!

I can confirm that if you do:

  • build library with ng build my-library --prod and
  • ctrl+shift+p and then select "Restart Angular Language server"

the error(s) of the type "'xyz' is not a known element" will be gone from the library's parent project.

As I understood it this is because --prod will (among other things) generate my-library.metadata.json file in dist folder which will then be used by the language server to i.e. recognize component selectors defined in my-library.

Now, one would expect that if I npm publish library built with ng build my-library --prod and then npm install that library into some other Angular app, the language server would see the metadata file in that installed npm package (in node_modules folder) and would not report "'xyz' is not a known element".

However, this is not working as expected and I can see the same error in a project that has npm installed my-library, even though there is a metadata json file present in my-library folder in node_modules.

Would this be the same bug as in this issue or a different bug?

Or is there some other (or additional) magical combination of keys to press or commands to give to the language server so it processes npm installed Angular libraries correctly?

It appears that the new way Ivy is working is to rely on metadata from .d.ts files and no longer from metadat.json files. The only reason why a --prod build is working is because your tsconfig is setting enableIvy to false (as recommended by angular for npm published libraries). This is a language service issue and not an angular cli issue, as the build will work just fine with or without Ivy for an application using the published library.

The issue is two-fold:

  1. Ivy removes the metadata.json files, required by ALS and other tools as well
  2. ALS is not currently smart enough to get the info from Ivy metadata instead of .metadata.json

Why is this a very annoying issue?

  • Ivy is the way to go, and library developers will make it the way to go as well,
  • when creating a library in your Ivy-based application project, you still want to use Ivy end-to-end in your app while still being a good citizen and publishing your reusable library to npm for others to use it.
  • most developers use npm link or point the tsconfig to the library dist directory for imports during the app development, that's the obvious way anyway,
  • it's annoying as hell to have vscode flagging things in your library as unknown,

Here is what I ended up doing to work around this issue, which may be acceptable to some people under the same circumstances. It won't help people who want to use their publishable libraries under the same conditions as a user of such libraries (i.e. from the published npm package):

Assuming you are using a monorepo or similar structure where the source code of the publishable library is accessible in a consistent manner to the application using it.

Let's assume the package is called 'happy-library'...

  1. Build (with --prod) and publish the library package to npm as usual. You must use --prod and have Ivy disabled in the build configuration,
  2. Update your tsconfig.json in the workspace root (or vscode will not figure it out...) to add a path mapping to that package, pointing to the source directory of the package.
  3. Import the package in the application code as if it were from node_modules, i.e. import {whatever} from 'happy-library';
    "paths": {
      "happy-library": ["libs/happy-library/src/index.ts"]
    }

It's not perfect, but at least I can use my own library in an end-to-end Ivy application, also made by me, without the errors in vscode, while still sharing the love and publishing it to NPM for other users, and I don't have to constantly yarn/npm link and debug why ALS is not working.

Interested in feedback if I may have missed something...

PS: fully working repo with this method at https://github.com/abdes/happy-coding

Has any progress been made on this.

Seems this will be available for beta-testing on Angular 11 scheduled for November.

See https://github.com/angular/vscode-ng-language-service/issues/335#issuecomment-693545000

I'm running on Angular 11 in my project (library built as well with Angular 11, with the --prod flag), and I have the issue decribed by @nprasovict . I published my library on Gitlab packages, and when I install it in our project with npm install, the Angular Language Service does not recognize my exported components coming from my library. Looks like it's been an issue for a very long time now, when can we expect it to be solved ?

I think I'll just end up removing the VSCode extension for now, but I'll be loosing a powerful development just because of this...

@JonWallsten Thanks, so it will be released soon if I understand well

This has been fixed by the new Ivy-native language service, released in v11.1.0.

Awesome work, @kyliau!
I see lot's of new errors in the template when it comes to strict null check and such that we've missed, really nice!

@kyliau Hmmmm... that's weird. I was having the very same problem with a directive declared in a library and I solved it by following the suggestion of building the library with the --prod switch. The thing is that I am already on ALS 11.1.1, so theoretically this would not have to be an issue anymore, right?
The project is a regular CLI multi-project, with some libs and an app.
Not sure about npm linking... I didn't do anything special. The library's path is listed in the root tsconfig.json.

I have the same issue. I build my lib with the --prod flag, so that ivy is disabled.
Linked the library dist folder, linked the package to my app and imported the libmodule. But still getting this error, that it is not a known angular element.
The component in the lib is in the declarations and in the exports array.

The component gets displayed, but still getting this error in vscode. tested versions:

11.1.3
11.2.1
0.1100.4

I agree, this probably shouldn't be closed @kyliau... I have a minimal reproducible example that I made for another problem that might serve to demonstrate this one as well. Have a look at this: https://github.com/vicatcu/monorepo-example-error (originally posted in connecction with this SO post)

I'll go a step further, if I add the "enableIvy": false option under the angularCompilerOptions in the tsconfig.lib.json apropos this comment, as I have done on this branch of my example repo, my errors vanish in vscode (granted my example project is still broken in some way I don't understand)

Just to clarify, being on v11.1.x is not enough, you have to enable Ivy mode by following the instructions here.
You should not have to change your tsconfig.*.json.
The fact that ... is not a known angular element showed up means you are not in Ivy mode.
To determine which mode you're on, go to the Output panel and look for Angular language service. It should mention Ivy. (see screenshot below).
Your project does not have to be using Ivy to use the Ivy language service, but you do have to be using Angular >= v9.

Screen Shot 2021-02-01 at 3 15 40 PM

If after verifying all of the above and the extension is still not working as expected, please open a new issue to help us triage and reduce noise. Thank you very much!

@kyliau thanks I, for one, had certainly missed that.

Was this page helpful?
0 / 5 - 0 ratings