html - คอมโพเนนต์ Custom Library ไม่ใช่องค์ประกอบที่รู้จัก แต่แอปสามารถคอมไพล์และรันได้
ปัญหา
ไฟล์ HTML ของฉันเตือนว่าคอมโพเนนต์/ไพพ์ที่กำหนดเองของฉัน 'ไม่ใช่องค์ประกอบที่รู้จัก' อย่างไรก็ตาม การสร้างและรันแอปพลิเคชัน ทำงานตามที่ตั้งใจไว้ และคอมโพเนนต์/ไพพ์ที่กำหนดเองสามารถทำงานได้ ความขัดแย้งระหว่างคอมโพเนนต์ที่ทำงานได้แต่แสดงเป็นข้อผิดพลาดนั้นรบกวนและอาจทำให้ทำงานได้ยาก ฉันรู้ว่านี่เป็นเรื่องเล็ก แต่ฉันอยากจะไม่เห็นข้อผิดพลาดในไฟล์ HTML ของฉันเมื่อไม่มีข้อผิดพลาดจริง ๆ
สรุป
ฉันมีโปรเจกต์ Angular สองโปรเจกต์ที่แตกต่างกัน; หนึ่งคือไลบรารี 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 {}
/*
* 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>
ไฟล์ด้านบนจะมีบรรทัดทั้งหมดที่อ้างอิงถึงคอมโพเนนต์ที่กำหนดเองของฉันขีดเส้นใต้สีแดงพร้อมข้อความข้อผิดพลาด 'my-theme-toggle' ไม่ใช่เอลิเมนต์ที่รู้จัก: ...หากใช่ ให้ตรวจสอบว่ามันเป็นส่วนหนึ่งของโมดูล.
ความพยายามในการแก้ไข
ฉันได้ลองหลายอย่างแล้ว แต่ก็ไม่มีผล
- ไม่ได้ใช้ NPM link และเพียงแค่คัดลอกไลบรารีที่สร้างโดย ng-packagr เข้าไปในโฟลเดอร์ node modules ของแอปพลิเคชันของฉัน
- สร้างใหม่และเชื่อมโยง/เริ่มต้นทุกอย่างใหม่
- กำลังค้นหาคำถามอื่น ๆ ใน S.O: ส่วนใหญ่ของคำถามเกี่ยวกับความล้มเหลวในการสร้างเนื่องจากการนำเข้า/ส่งออกนั้นไม่ถูกต้องจริง ๆ
ความรู้สึกเฉพาะตัวของฉัน
ฉันคิดว่านี่เป็นปัญหาที่ตัวเลือกคอมไพเลอร์ paths ใน tsconfig.json ของแอปพลิเคชันที่ใช้งาน จากการค้นคว้าของฉันทั้งหมด นี่คือสิ่งเดียวที่ปรากฏขึ้นบ่อยกว่าสิ่งอื่น ๆ ตอนนี้ฉันยังไม่ได้ตั้งค่า path เพราะทุกอย่างใช้งานได้ ไลบรารีทั่วไปของฉันดูและทำงานเหมือนไลบรารี node_module อื่น ๆ ยกเว้นปัญหานี้
ความคิดอีกอย่างของฉันคือ เพราะทุกอย่างทำงานและรันได้ ดังนั้นปัญหาอาจอยู่ที่ vs-code ที่ไม่เข้าใจการนำเข้า หรืออะไรทำนองนั้น แต่อย่างไรก็ตามฉันคิดว่าสิ่งนี้ไม่น่าจะเกิดขึ้น
ฉากหลัง
ทั้งสองโปรเจกต์ Angular อยู่บนเวอร์ชัน 9, rc7 ฉันใช้ ng-packagr ในการสร้างไลบรารีของฉัน ฉันใช้ Visual Studio Code และในขณะที่เขียน ฉันอยู่บนเวอร์ชันล่าสุด
แก้ไข ปัญหานี้หายไปหลังจากอัปเกรดเป็น Angular 11 ผมคิดว่าหลายปัญหาอื่น ๆ อาจจะช่วยแก้ไขได้ แต่สิ่งนี้รู้สึกว่าเป็นตัวเลือกที่ดีที่สุด
คำตอบ #1
มันเป็นปัญหาสำคัญ 99.99% ของเวลา!
ฉันเคยเห็นคำถามนี้ถูกโพสต์ในหลากหลายรูปแบบในหลายเว็บไซต์ ทั้งในและนอก Stack Overflow ฉันสามารถบอกคุณได้ว่ามันอาจจะไม่ใช่ปัญหาของ Angular Language Service
มีสามสาเหตุที่สิ่งนี้สามารถเกิดขึ้นได้
คุณได้ส่งออกคอมโพเนนต์ที่หายไปจากไลบรารีแล้วหรือยัง เช่น ตรวจสอบว่าคุณ:
- เพิ่ม
export * from <your-component>เข้าไปในไฟล์public-api.tsของคุณ
- เพิ่ม
- เพิ่มคอมโพเนนต์ของคุณไปที่
exportsของโมดูลไลบรารีที่ส่งออกมัน วิธีที่คุณกำลังนำเข้าคอมโพเนนต์ของไลบรารี เช่น ตรวจสอบว่าคุณ:
- เชื่อมโยงไลบรารี?
cd /path/to/<your-library> && npm link
- เชื่อมโยงไลบรารี?
- เชื่อมโยงแอปพลิเคชันหรือไม่?:
cd /path/to/app && npm link <your-library> - ได้เพิ่มไลบรารี NgModule(s)
YourLibraryModuleเข้ากับimports:[]ของ NgModule หลักของแอปพลิเคชันของคุณ คุณอาจลืมประกาศคอมโพเนนต์หลักใน App NgModule ของคุณ!!
- อันนี้ใหญ่มากและไม่ค่อยถูกพูดถึงบ่อย ใน Angular 10, 11 คุณอาจลืมเพิ่ม Application Component ไปยัง
declarationsที่อ้างอิง Component ของไลบรารีที่หายไป และบริการภาษาหรือคอมไพเลอร์จะแจ้งว่าขาด Library Component แต่จะไม่บอกว่า App Component ถูกส่งออกอย่างไม่ถูกต้อง!
- อันนี้ใหญ่มากและไม่ค่อยถูกพูดถึงบ่อย ใน Angular 10, 11 คุณอาจลืมเพิ่ม Application Component ไปยัง
ทำไมต้องรีสตาร์ท Angular Language Service?
บางครั้งข้อผิดพลาดอาจเปลี่ยนไปเมื่อคุณเริ่มบริการภาษาใหม่ (เช่น การรีสตาร์ท 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
และวัวล่า!! คุณเห็นปัญหาที่แท้จริงแล้ว การแก้มันก็ง่าย!
คำตอบ #2
ในการแก้ไขปัญหา ขณะนี้คุณต้องสร้างด้วยแฟลกการผลิต --prod เพราะในสถานะปัจจุบัน Angular Language Server ไม่ทำงานกับการสร้างแบบ Ivy โดยค่าเริ่มต้น การสร้างโปรดักชันของ Angular จะสร้างโดยไม่ใช้ Ivy ดังนั้นเมื่อมีการสร้าง มันจะสร้างไฟล์ lib.metadata.json ไฟล์นี้คือไฟล์ที่ language server ใช้เพื่อให้ปลั๊กอินทำงาน
ในไลบรารีของคุณ, สร้าง build
ng build <lib> --prod- เพิ่มแฟลก
--watchเพื่อติดตามการเปลี่ยนแปลง
- เพิ่มแฟลก
ในห้องสมุดของคุณ สร้างลิงก์
cd distแล้วnpm linkฉันสร้าง
package.jsonในโฟลเดอร์distและสร้างลิงก์ที่นั่นเนื่องจากไลบรารีของฉันมีหลายโมดูลในนั้น ซึ่งจะช่วยให้คุณสามารถทำได้import { ModuleAComponent } from '<lib>/moduleA'
- ฉันได้สร้าง
package.jsonในโฟลเดอร์distและสร้างลิงก์ที่นั่นเพราะไลบรารีของฉันมีหลายโมดูลอยู่ในนั้น ซึ่งจะทำให้คุณสามารถทำ import { ModuleAComponent } from '<lib>/moduleA'import { ModuleADirective } from '<lib>/moduleA'- หมายเหตุ: โฟลเดอร์ที่คุณลิงก์ต้องมี
package.jsonมิฉะนั้นมันจะใช้รากของโปรเจ็กต์เนื่องจากนั่นคือpackage.jsonที่ใกล้ที่สุด - ถ้าคุณทำแบบเดียวกัน เส้นทางด้านล่างจะอยู่ในรูปแบบที่ถูกต้อง ไม่เช่นนั้นอาจจะไม่เป็น และคุณสามารถลอง:
"lib": ["./node_modules/lib", "./node_modules/lib/*"] - ในแอปพลิเคชันของคุณ, ลิงก์ไปยังแพ็กเกจ
npm link <lib> - ในแอปพลิเคชันของคุณ ให้สร้าง
pathในtsconfig.base.jsonของคุณ (เส้นทางอาจแตกต่างกันขึ้นอยู่กับวิธีที่คุณสร้างลิงก์ของคุณ) - ในแอปพลิเคชันของคุณ, รีสตาร์ท Angular Language Server
{
"compilerOptions": {
"paths": {
"lib/*": [
"./node_modules/lib/*"
]
}
}
}
