自定义库组件不是已知元素,但应用程序编译并运行

Zen*_*en 25 html npm typescript visual-studio-code angular

问题

我的 html 文件警告我的自定义组件/管道“不是已知元素”。然而,构建和运行应用程序按预期工作,并且自定义组件/管道可以正常工作。组件工作但显示为错误的二分法令人讨厌并且可能难以使用。我知道这是一件小事,但我真的不想在没有错误的情况下在我的 html 文件中看到错误。

概括

我有两个不同的角度项目;我在我的 angular 应用程序中使用的 angular 库。该库导出应用程序使用的多个自定义组件、管道和服务。我没有通过 npm 发布这个库,而是使用 npm-link 为应用程序提供对该库的访问权限。这似乎可以作为我的应用程序组件中定义的任何服务/组件工作并且不会抱怨。尽管我将库中的任何内容放入模板文件的那一刻,该选择器带有下划线并出现警告。

文件

/*Library Module*/
@NgModule({
  declarations: [
    ThemeToggleComponent,
    // Other custom components/pipes
  ],
  exports: [
    ThemeToggleComponent,
    // Other components needed in templates files
  ]
})
export class MyCommonModule {}
  
Run Code Online (Sandbox Code Playgroud)
/*
 * Public API Surface of my-common library
 */

export * from './lib/my-common.module';
/*
 * Many other components, services, pipes, etc etc
 */
export * from './lib/theme-toggle/theme-toggle.component';

Run Code Online (Sandbox Code Playgroud)
/* Consuming Application module */
import { MyCommonModule } from 'my-common';

@NgModule({
  imports: [
    MyCommonModule,
  ],
  declarations: [
    MyComponent,
  ],
})
export class MyModule {}
Run Code Online (Sandbox Code Playgroud)
/* Template of MyComponent, my.component.html */
<div>
  <my-theme-toggle (darkThemeSelected)="toggleTheme($event)"></my-theme-toggle>
</div>
Run Code Online (Sandbox Code Playgroud)

上面的文件将所有引用我的自定义组件的行都标有红色下划线,并带有错误消息“my-theme-toggle”不是已知元素:...如果是,请验证它是模块的一部分

尝试修复

我尝试了一些东西,但无济于事

  • 不使用 NPM 链接,只是将 ng-packagr 创建的库复制到我的应用程序的节点模块中
  • 重建和重新链接/重新启动一切
  • 搜索其他 SO 问题:大多数问题都与构建失败有关,因为导入/导出实际上不正确。

我的预感

我认为这是消费应用程序中 tsconfig.json 中的路径编译器选项的问题。在我所有的研究中,这是最重要的一件事。我目前没有设置路径,因为一切正常。除了这个问题之外,我的公共库的外观和行为与任何其他 node_module 库相似。

我的另一个想法是,因为一切正常并运行,那么问题可能在于 vs-code 不理解导入,或者类似的东西。虽然我认为这不太可能。

背景

两个 angular 项目都在版本 9,rc7 上。我使用 ng-packagr 来构建我的库。我使用 Visual Studio 代码,在撰写本文时,我使用的是最新版本。

编辑 这个问题在升级到 angular 11 后就消失了,我认为其他几个问题可能会解决它,但这感觉像是最好的选择。

Dec*_*ded 14

99.99% 的情况都是导入问题!

我看到这个问题在 Stack Overflow 内外的不同网站上以略有不同的方式发布。我可以告诉你,这可能不是 Angular Language Service 的问题。

发生这种情况的原因有以下三个

  1. 您如何从库中导出缺少的组件,例如检查您是否:

    • 添加export * from <your-component>到您的public-api.ts文件中
    • 将您的组件添加到exports导出它的库模块中
  2. 您如何导入库组件,例如检查您是否:

    • 链接图书馆?cd /path/to/<your-library> && npm link
    • 链接应用程序?:cd /path/to/app && npm link <your-library>
    • 将库 NgModule 添加YourLibraryModuleimports:[]应用程序主 NgModule 中
  3. 您可能忘记在您的 App NgModule 中声明父组件!

    • 这个问题很大,但不常被提及。在 Angular 10、11 中,您可能会忘记添加declarations引用缺少的库组件的应用程序组件,并且语言服务/编译器会抱怨缺少库组件,但更不用说应用程序组件被错误导出了!

为什么 Angular 语言服务会重启?

有时,一旦重新启动语言服务(例如重新启动 VSCode),错误可能会发生变化。对于我上面提到的场景 3,错误变为:

Error: Cannot determine the module for class YourAppComponent in YourApp/src/app/components/your-app-component/your-app-component.component.ts! Add YourAppComponent to the NgModule to fix it
Run Code Online (Sandbox Code Playgroud)

瞧!您看到真正的问题并且解决它很容易!

  • 这应该是公认的答案。“将您的组件添加到导出它的库模块的导出中”是让我丧命的原因。 (4认同)

Get*_*awn 10

要解决此问题,您目前必须使用生产标志进行构建--prod,因为在当前状态下,Angular 语言服务器不支持 Ivy构建。默认情况下,angular prod 构建构建时不使用 Ivy。因此,当它被构建时,它会创建一个lib.metadata.json文件。这是语言服务器用来使插件工作的文件。

  1. 在您的库中,创建一个构建ng build <lib> --prod
    • 添加--watch标志以观察变化
  2. 在您的库中,创建一个链接cd dist然后npm link
    • package.jsondist文件夹中创建了一个并在那里创建了链接,因为我的库中有多个模块。这将允许你做
      • import { ModuleAComponent } from '<lib>/moduleA'
      • import { ModuleADirective } from '<lib>/moduleA'
    • 注意:您链接的文件夹必须有一个,package.json否则它将使用项目的根目录,因为它是最接近的package.json
    • 如果你这样做,下面的路径格式正确,否则它们可能不是,你可以尝试: "lib": ["./node_modules/lib", "./node_modules/lib/*"]
  3. 在您的应用程序中,链接到包npm link <lib>
  4. 在您的应用程序中path在您的tsconfig.base.json(路径可能不同,具体取决于您创建链接的方式)
  5. 在您的应用程序中,重新启动 Angular 语言服务器
{
  "compilerOptions": {
    "paths": {
      "lib/*": [
        "./node_modules/lib/*"
      ]
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Wol*_*359 6

直到最近我才遇到这种描述的错误。

卸载 Angular 语言服务扩展(我最近安装的)后,错误消失了。

  • 已验证这确实有效,但我对接受这个答案感到不安。Angular 语言服务对于捕获常见错误、自动完成变量名称和许多其他事情非常有用。不过,这可能暗示了问题的潜在根源。 (2认同)
  • 为什么不更新这个答案来解释如何“重新启动”Angular 语言服务:) (2认同)