html - Custom Library-komponenten är inte ett känt element, men appen kompileras och körs
Problemet
Mina HTML-filer varnar för att mina egna komponenter/pipes 'inte är ett känt element'. Men att bygga och köra applikationen fungerar som avsett, och de egna komponenterna/pipes fungerar. Dissonansen mellan att komponenterna fungerar men visas som fel är irriterande och kan vara svår att hantera. Jag vet att detta är en liten sak, men jag vill verkligen inte se fel i mina HTML-filer när det inte finns några fel.
Sammanfattning
Jag har två separata Angular-projekt; ett Angular-bibliotek som jag använder med min Angular-applikation. Biblioteket exporterar flera egna komponenter, pipes och tjänster som applikationen använder. Jag har inte publicerat detta bibliotek via npm, istället använder jag npm-link för att ge applikationen åtkomst till biblioteket. Detta verkar fungera eftersom alla tjänster/komponenter som definieras i mina applikationskomponenter fungerar och inte ger några felmeddelanden. Men så snart jag lägger något från mitt bibliotek i min template-fil blir den selektorn understruken och en varning visas.
Filerna
/*Library Module*/
@NgModule({
declarations: [
ThemeToggleComponent,
// Other custom components/pipes
],
exports: [
ThemeToggleComponent,
// Other components needed in templates files
]
})
export class MyCommonModule {}
/*
* 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';
/* Consuming Application module */
import { MyCommonModule } from 'my-common';
@NgModule({
imports: [
MyCommonModule,
],
declarations: [
MyComponent,
],
})
export class MyModule {}
/* Template of MyComponent, my.component.html */
<div>
<my-theme-toggle (darkThemeSelected)="toggleTheme($event)"></my-theme-toggle>
</div>
Filen ovan kommer att ha alla rader som refererar till mina anpassade komponenter understrukna i rött med felmeddelandet 'my-theme-toggle' är inte ett känt element: ...om det är det, kontrollera att det är en del av modulen.
Försök att fixa
Jag har provat flera saker, men utan resultat
- Att inte använda NPM-länk och bara kopiera biblioteket som skapats av ng-packagr till node-modulerna i min applikation
- Bygger om och länkar om/startar om allt
- Söker efter andra S.O-frågor: de flesta frågor handlar om byggfel eftersom importen/exporten faktiskt var felaktig.
Mina magkänslor
Jag tror att detta är ett problem med paths-kompilatoralternativet i tsconfig.json i den konsumerande applikationen. Genom all min forskning är detta det enda som dyker upp mer än något annat. Jag har för närvarande ingen sökväg inställd, eftersom allt fungerar. Mitt gemensamma bibliotek ser ut och fungerar som vilket annat node_module-bibliotek som helst, förutom detta problem.
Min andra tanke är att eftersom allt fungerar och körs, kan problemet vara att vs-code inte förstår importen, eller något i den stilen. Även om jag tror att detta är osannolikt.
Bakgrunden
Båda Angular-projekten är på version 9, rc7. Jag använder ng-packagr för att bygga mitt bibliotek. Jag använder Visual Studio Code, och vid tidpunkten för skrivandet är jag på den senaste utgåvan.
REDIGERA Detta problem försvann efter uppgradering till Angular 11, jag tror att flera av de andra problemen kan lösas med det, men detta känns som det bästa alternativet.
Svar #1
Det är ett importproblem, 99,99 % av tiden!
Jag har sett den här frågan ställas på lite olika sätt på olika sajter, både inom och utanför Stack Overflow. Jag kan säga att det troligen inte är ett problem med Angular Language Service.
Det finns tre skäl till att detta kan hända
hur du har exporterat den saknade komponenten från biblioteket, t.ex. kontrollera om du:
- Lade till
export * from <your-component>i dinpublic-api.ts-fil
- Lade till
- Lade till din komponent i
exportsi Biblioteksmodulen som exporterar den hur du importerar Biblioteks-Komponenten, t.ex. kontrollera om du:
- länkade biblioteket?
cd /path/to/<ditt-bibliotek> && npm link
- länkade biblioteket?
- länkade applikationen?:
cd /path/to/app && npm link <your-library> - lade till biblioteket NgModule(s)
YourLibraryModuletillimports:[]i din applikations huvud-NgModule Du kanske glömde att deklarera föräldrakomponenten i din App NgModule!!
- Den här är enorm och nämns inte ofta. I Angular 10, 11 kan du glömma att lägga till Applikationskomponenten i
declarationssom refererar till den saknade bibliotekskomponenten, och språkservicen/kompilatorn kommer att klaga på att Bibliotekskomponenten saknas, men nämner inte att App-komponenten är exporterat på fel sätt!
- Den här är enorm och nämns inte ofta. I Angular 10, 11 kan du glömma att lägga till Applikationskomponenten i
Varför startar Angular Language Service om?
Ibland kan felet förändras när du startar om språktjänsten (t.ex. starta om VSCode). För scenario 3 som jag nämnde ovan blir felet:
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
Och voilà!! Du ser det verkliga problemet och att fixa det är enkelt!
Svar #2
För att åtgärda problemet måste du för närvarande bygga med produktionsflaggan --prod, eftersom Angular Language Server i sitt nuvarande tillstånd inte fungerar med Ivy-byggnader. Som standard bygger den angular prod-byggnaden utan Ivy. Så när den byggs skapas en lib.metadata.json-fil. Detta är filen som språkservern använder för att få pluginet att fungera.
I ditt bibliotek, skapa en build
ng build <lib> --prod- lägg till
--watch-flaggan för att övervaka förändringar
- lägg till
I ditt bibliotek, skapa en länk
cd distsedannpm linkJag skapade en
package.jsonidist-mappen och skapade länken där eftersom mitt bibliotek har flera moduler i det. Detta kommer att tillåta dig att göraimport { ModuleAComponent } from '<lib>/moduleA'
- Jag skapade en
package.jsonidist-mappen och skapade länken där eftersom mitt bibliotek har flera moduler i det. Detta kommer att tillåta dig att göra import { ModuleAComponent } from '<lib>/moduleA'import { ModuleADirective } from '<lib>/moduleA'- Observera: Mappen du länkar måste ha en
package.json, annars kommer den att använda projektets rot eftersom det är den närmastepackage.json - Om du gör samma sak är vägarna nedan i korrekt format, annars kanske de inte är det och du kan försöka:
"lib": ["./node_modules/lib", "./node_modules/lib/*"] - I din applikation, länka till paketet
npm link <lib> - I din applikation, skapa en
pathi dintsconfig.base.json(Sökvägen kan vara olika beroende på hur du skapade din länk) - I din applikation, starta om Angular-språkservern
{
"compilerOptions": {
"paths": {
"lib/*": [
"./node_modules/lib/*"
]
}
}
}
