การใช้สถาปัตยกรรมปลั๊กอิน / ระบบปลั๊กอิน / เฟรมเวิร์กแบบเสียบได้ใน Angular 2, 4, 5, 6


136

อัปเดต 5/24/2018:ตอนนี้เราเป็น Angular เวอร์ชัน +3 จากโพสต์เดิมของฉันและยังไม่มีวิธีแก้ไขขั้นสุดท้ายที่สามารถใช้งานได้ Lars Meijdam (@LarsMeijdam) ได้เสนอแนวทางที่น่าสนใจซึ่งคุ้มค่าแก่การดู (เนื่องจากปัญหาด้านกรรมสิทธิ์เขาจึงต้องลบที่เก็บ GitHub ชั่วคราวซึ่งเขาเคยโพสต์ตัวอย่างของเขาอย่างไรก็ตามคุณสามารถส่งข้อความถึงเขาโดยตรงหากคุณต้องการสำเนาโปรดดูความคิดเห็นด้านล่างสำหรับข้อมูลเพิ่มเติม)

การเปลี่ยนแปลงทางสถาปัตยกรรมล่าสุดใน Angular 6 ทำให้เราเข้าใกล้โซลูชันมากขึ้น นอกจากนี้ Angular Elements ( https://angular.io/guide/elements ) ยังมีฟังก์ชั่นส่วนประกอบบางอย่างแม้ว่าจะไม่ใช่สิ่งที่ฉันอธิบายไว้ในโพสต์นี้ในตอนแรก

หากใครจากทีม Angular ที่น่าทึ่งบังเอิญเจอสิ่งนี้โปรดทราบว่าดูเหมือนจะมีคนอื่น ๆ อีกมากมายที่สนใจฟังก์ชันนี้เช่นกัน อาจเป็นเรื่องที่ควรพิจารณาสำหรับงานในมือ


ผมอยากจะใช้ pluggable (Plug-in) ในกรอบAngular 2, Angular 4, Angular 5หรือAngular 6แอพลิเคชัน

(กรณีการใช้งานเฉพาะของฉันสำหรับการพัฒนาเฟรมเวิร์กที่เสียบได้นี้คือฉันจำเป็นต้องพัฒนาระบบการจัดการเนื้อหาขนาดเล็กด้วยเหตุผลหลายประการที่ไม่จำเป็นต้องอธิบายไว้ในที่Angular 2/4/5/6นี้จึงเป็นความเหมาะสมที่ใกล้เคียงที่สุดสำหรับความต้องการส่วนใหญ่ของระบบนั้น)

โดยเฟรมเวิร์กแบบเสียบได้ (หรือสถาปัตยกรรมปลั๊กอิน) ฉันหมายถึงระบบที่อนุญาตให้นักพัฒนาบุคคลที่สามสร้างหรือขยายฟังก์ชันการทำงานของแอปพลิเคชันหลักโดยใช้ส่วนประกอบที่เสียบได้โดยไม่ต้องเข้าถึงโดยตรงหรือรู้เกี่ยวกับซอร์สโค้ดของแอปพลิเคชันหลัก หรืองานภายใน

(วลีที่เกี่ยวกับ " โดยไม่ต้องเข้าถึงโดยตรงหรือรู้เกี่ยวกับซอร์สโค้ดของแอปพลิเคชันหรือการทำงานภายใน " เป็นวัตถุประสงค์หลัก)

ตัวอย่างของกรอบ pluggable รวมทั่วไประบบการจัดการเนื้อหาเหมือนหรือWordPressDrupal

สถานการณ์ในอุดมคติ (เช่นเดียวกับ Drupal) คือการวางส่วนประกอบที่เสียบได้ (หรือปลั๊กอิน) เหล่านี้ลงในโฟลเดอร์โดยอัตโนมัติให้แอปพลิเคชันตรวจหาหรือค้นพบโดยอัตโนมัติและทำให้ "ทำงาน" ได้อย่างน่าอัศจรรย์ การที่สิ่งนี้เกิดขึ้นในลักษณะ Hot-Pluggable ซึ่งหมายความว่าในขณะที่แอปกำลังทำงานอยู่จะเหมาะสมที่สุด

ขณะนี้ฉันกำลังพยายามหาคำตอบ ( ด้วยความช่วยเหลือของคุณ ) สำหรับคำถามห้าข้อต่อไปนี้

  1. การปฏิบัติจริง:โครงร่างปลั๊กอินสำหรับAngular 2/4/5/6แอปพลิเคชันสามารถใช้งานได้จริงหรือไม่? (จนถึงตอนนี้ฉันยังไม่พบวิธีที่เป็นประโยชน์ในการสร้างเฟรมเวิร์กที่เสียบได้อย่างแท้จริงด้วยAngular2/4/5/6)
  2. ความท้าทายที่คาดหวัง:อาจพบความท้าทายอะไรบ้างในการนำโครงงานปลั๊กอินไปใช้กับAngular 2/4/5/6แอปพลิเคชัน
  3. กลยุทธ์การใช้งาน: สามารถใช้เทคนิคหรือกลยุทธ์เฉพาะใดในการใช้กรอบปลั๊กอินสำหรับAngular 2/4/5/6แอปพลิเคชัน
  4. แนวทางปฏิบัติที่ดีที่สุด: แนวทางปฏิบัติที่ดีที่สุดในการนำระบบปลั๊กอินไปใช้กับAngular 2/4/5/6แอปพลิเคชันคืออะไร
  5. ทางเลือกเทคโนโลยี: ถ้ากรอบปลั๊กอินเป็นไม่ได้ในทางปฏิบัติในAngular 2/4/5/6การประยุกต์ใช้สิ่งที่ค่อนข้างเทียบเท่าเทคโนโลยี (เช่นReact) อาจจะเหมาะสำหรับเว็บแอพพลิเคชันที่ทันสมัยปฏิกิริยาสูง ?

โดยทั่วไปการใช้Angular 2/4/5/6เป็นที่พึงปรารถนามากเนื่องจาก:

  • มันเร็วมากโดยธรรมชาติอย่างเห็นได้ชัด
  • ใช้แบนด์วิดท์น้อยมาก (หลังจากโหลดครั้งแรก)
  • มีรอยเท้าค่อนข้างเล็ก (หลังAOTและtree shaking) - และรอยเท้านั้นยังคงหดตัว
  • มันทำงานได้ดีและทีม Angular และชุมชนกำลังเติบโตอย่างรวดเร็วของระบบนิเวศ
  • มันเล่นได้ดีกับเทคโนโลยีเว็บที่ดีที่สุดและล่าสุดมากมายเช่นTypeScriptและObservables
  • Angular 5 รองรับพนักงานบริการแล้ว ( https://medium.com/@webmaxru/a-new-angular-service-worker-creating-automatic-progressive-web-apps-part-1-theory-37d7d7647cc7 )
  • ได้รับการสนับสนุนโดยGoogleก็มีโอกาสที่จะได้รับการสนับสนุนและเพิ่มดีในอนาคต

ฉันต้องการใช้Angular 2/4/5/6สำหรับโครงการปัจจุบันของฉันเป็นอย่างมาก ถ้าฉันสามารถใช้Angular 2/4/5/6ฉันจะใช้Angular-CLIและอาจจะAngular Universal(สำหรับการแสดงผลฝั่งเซิร์ฟเวอร์)

นี่คือความคิดของฉันเกี่ยวกับคำถามข้างต้น โปรดตรวจสอบและให้ข้อเสนอแนะและการตรัสรู้ของคุณ

  • Angular 2/4/5/6แอปใช้แพ็คเกจ - แต่ไม่จำเป็นต้องเหมือนกับการอนุญาตปลั๊กอินภายในแอปพลิเคชัน คุณสามารถเพิ่มปลั๊กอินในระบบอื่น ๆ (เช่นDrupal) ได้โดยการวางโฟลเดอร์ปลั๊กอินลงในไดเร็กทอรีโมดูลทั่วไปซึ่งระบบจะ "หยิบ" ขึ้นมาโดยอัตโนมัติ ในAngular 2/4/5/6แพคเกจ (อาจเป็นปลั๊กอิน) มักจะติดตั้งผ่านnpmเพิ่มไปยังpackage.jsonแล้วนำเข้าสู่แอปด้วยตนเองเช่นเดียวกับในapp.module. สิ่งนี้ซับซ้อนกว่าDrupalวิธีการวางโฟลเดอร์และให้ระบบตรวจจับแพ็คเกจโดยอัตโนมัติ ยิ่งการติดตั้งปลั๊กอินมีความซับซ้อนมากเท่าไหร่ก็จะมีโอกาสน้อยที่ผู้คนจะใช้งานได้ มันจะดีกว่ามากถ้ามีวิธีสำหรับAngular 2/4/5/6เพื่อตรวจหาและติดตั้งปลั๊กอินโดยอัตโนมัติ ฉันสนใจมากที่จะค้นหาวิธีการที่ช่วยให้ผู้ที่ไม่ใช่นักพัฒนาสามารถติดตั้งAngular 2/4/5/6แอปพลิเคชันและติดตั้งปลั๊กอินที่เลือกโดยไม่ต้องเข้าใจสถาปัตยกรรมของแอปพลิเคชันทั้งหมด

  • โดยทั่วไปประโยชน์อย่างหนึ่งของการจัดหาสถาปัตยกรรมแบบเสียบได้คือการที่นักพัฒนาบุคคลที่สามสามารถขยายการทำงานของระบบได้ง่ายมาก เห็นได้ชัดว่านักพัฒนาเหล่านี้จะไม่คุ้นเคยกับความซับซ้อนทั้งหมดของโค้ดสำหรับแอปพลิเคชันที่พวกเขาเสียบเข้า เมื่อพัฒนาปลั๊กอินแล้วผู้ใช้ด้านเทคนิครายอื่น ๆ ก็สามารถติดตั้งแอปพลิเคชันและปลั๊กอินที่เลือกได้ อย่างไรก็ตามAngular 2/4/5/6ค่อนข้างซับซ้อนและมีช่วงการเรียนรู้ที่ยาวมาก สิ่งที่ซับซ้อนต่อไปส่วนใหญ่การผลิตAngular 2/4/5/6การใช้งานนอกจากนี้ยังใช้Angular-CLI, และAngular Universal WebPackคนที่ใช้ปลั๊กอินอาจจะต้องมีความรู้พื้นฐานอย่างน้อยว่าสิ่งเหล่านี้เข้ากันได้อย่างไร - พร้อมกับความรู้ในการทำงานที่ดีTypeScriptNodeJSและความคุ้นเคยที่เหมาะสมกับ ข้อกำหนดด้านความรู้มีมากจนไม่มีบุคคลที่สามต้องการพัฒนาปลั๊กอินหรือไม่?

  • ปลั๊กอินส่วนใหญ่มักจะมีส่วนประกอบฝั่งเซิร์ฟเวอร์ (เช่นสำหรับจัดเก็บ / เรียกข้อมูลที่เกี่ยวข้องกับปลั๊กอิน) รวมถึงเอาต์พุตฝั่งไคลเอ็นต์บางส่วน Angular 2/4/5โดยเฉพาะ (และอย่างยิ่ง) ไม่สนับสนุนนักพัฒนาจากการฉีดเทมเพลตของตนเองในขณะรันไทม์เนื่องจากอาจก่อให้เกิดความเสี่ยงด้านความปลอดภัยอย่างร้ายแรง ในการจัดการเอาต์พุตหลายประเภทที่ปลั๊กอินอาจรองรับได้ (เช่นการแสดงกราฟ) ดูเหมือนว่าการอนุญาตให้ผู้ใช้สร้างเนื้อหาที่ถูกแทรกเข้าไปในสตรีมการตอบกลับในรูปแบบอื่นเป็นสิ่งที่จำเป็น ฉันสงสัยว่ามันจะเป็นไปได้อย่างไรที่จะรองรับความต้องการนี้โดยไม่ต้องใช้Angular 2/4/5/6กลไกการรักษาความปลอดภัยโดยเปรียบเปรย

  • Angular 2/4/5/6แอ็พพลิเคชันการผลิตส่วนใหญ่คอมไพล์ล่วงหน้าโดยใช้คอมไพล์Ahead of Time( AOT) (อาจเป็นไปได้ทั้งหมด) ฉันไม่แน่ใจว่าจะเพิ่มปลั๊กอินไปยัง (หรือรวมเข้ากับ) แอปพลิเคชันที่รวบรวมไว้ล่วงหน้าได้อย่างไร สถานการณ์ที่ดีที่สุดคือการรวบรวมปลั๊กอินแยกจากแอปพลิเคชันหลัก อย่างไรก็ตามฉันไม่แน่ใจว่าจะทำงานนี้อย่างไร ทางเลือกอาจเป็นการคอมไพล์แอปพลิเคชันทั้งหมดอีกครั้งด้วยปลั๊กอินใด ๆ ที่รวมอยู่ แต่จะทำให้เกิดความซับซ้อนขึ้นเล็กน้อยสำหรับผู้ใช้ระดับผู้ดูแลระบบที่ต้องการติดตั้งแอปพลิเคชัน (บนเซิร์ฟเวอร์ของตัวเอง) พร้อมกับปลั๊กอินที่เลือก

  • ในAngular 2/4/5/6แอปพลิเคชันโดยเฉพาะแอปพลิเคชันที่รวบรวมไว้ล่วงหน้าโค้ดที่ผิดพลาดหรือขัดแย้งกันเพียงชิ้นเดียวสามารถทำลายแอปพลิเคชันทั้งหมดได้ Angular 2/4/5/6แอปพลิเคชันไม่ใช่วิธีแก้จุดบกพร่องที่ง่ายที่สุดเสมอไป การใช้ปลั๊กอินที่มีพฤติกรรมไม่เหมาะสมอาจส่งผลให้เกิดประสบการณ์ที่ไม่พึงประสงค์ ขณะนี้ฉันไม่ทราบถึงกลไกในการจัดการปลั๊กอินที่มีพฤติกรรมไม่เหมาะสม


1
ในความเห็นของฉันโมดูลเชิงมุม 2 เป็นปลั๊กอิน @ angular / router, @ angular / form, @ angular / http, @ angular / material ซึ่งเป็น 'ปลั๊กอิน' จากเชิงมุมเราสามารถตรวจสอบว่าพวกเขาสร้าง 'ปลั๊กอิน' ได้อย่างไร
Timathon

8
@ Timathon น่าเสียดายที่พวกเขาไม่เหมือนกัน ระบบปลั๊กอินอนุญาตให้ขยายแอปพลิเคชันได้โดยไม่ต้องแก้ไขรหัสแอปพลิเคชันหลัก การใช้ @ angular / router, @ angular / form ฯลฯ กำหนดให้ผู้ใช้แก้ไขแอปพลิเคชัน สิ่งเหล่านี้เป็นไลบรารีจริง ๆ เมื่อเทียบกับปลั๊กอิน ฉันสนใจที่จะอนุญาตให้ผู้ดูแลระบบที่ไม่ใช่นักพัฒนาสามารถเลือกและใช้ปลั๊กอินที่น่าสนใจที่สุดสำหรับพวกเขาโดยไม่ต้องรับรู้รายละเอียดภายในของแอปพลิเคชัน
Anthony Gatlin

1
คุณไปได้ทุกที่กับสิ่งนี้หรือไม่? ฉันสนใจที่จะลองสิ่งที่คล้ายกัน วิธีการสร้าง Angular 2 (รอบ ๆ โมดูล) ฉันคิดว่าสถาปัตยกรรมประเภทปลั๊กอินจะเข้ากันได้ดีจริงๆ แต่ดูเหมือนจะไม่เป็นตัวอย่างใด ๆ
โจ

2
@ โจฉันยังไม่มีทางออกที่ดีสำหรับปัญหานี้ ฉันคิดเช่นเดียวกับคุณ
Anthony Gatlin

2
ฉันสร้างที่เก็บบน github ด้วยโซลูชันที่อาจช่วยได้ มันใช้ไลบรารี Angular 6 และแอพพลิเคชั่นพื้นฐาน 1 ตัวซึ่งโหลดไลบรารีที่รวม UMD อย่างเกียจคร้าน github.com/lmeijdam/angular-umd-dynamic-example หากคุณมีข้อเสนอแนะใด ๆ โปรดอย่าลังเลที่จะเพิ่ม!
Lars Meijdam

คำตอบ:


17

ฉันสร้างที่เก็บบน github ด้วยโซลูชันที่อาจช่วยได้ มันใช้ไลบรารี Angular 6 และแอพพลิเคชั่นพื้นฐาน 1 ตัวซึ่งโหลดไลบรารีที่รวม UMD อย่างเกียจคร้าน https://github.com/lmeijdam/angular-umd-dynamic-example

หากคุณมีข้อเสนอแนะโปรดอย่าลังเลที่จะเพิ่ม!


2
ดังที่ได้กล่าวไว้ในความคิดเห็นอื่นฉันต้องทำให้ที่เก็บเป็นแบบส่วนตัวเนื่องจากนโยบายของ บริษัท .. ฉันจะนำกลับมาออนไลน์ในภายหลังเนื่องจากการสนทนากำลังดำเนินอยู่
Lars Meijdam

ชอบที่จะเห็นวิธีแก้ปัญหาของคุณโปรด
Subhan

@Subhan ตอนนี้ฉันยุ่งอยู่กับการเขียนที่เก็บใหม่ก่อนที่จะวางกลับใน GH อีกครั้ง ให้เวลาฉันอีกสักหน่อย มิฉะนั้นคุณสามารถติดต่อฉันได้โดยตรง! : D
Lars Meijdam

@ lars-meijdam: เราจะยังรออีกมาก: D ... ฉันสนใจมากเช่นกัน ขอบคุณล่วงหน้า
aguetat

17

อัปเดต

สำหรับAngular 11ฉันขอแนะนำให้คุณดูการใช้งานกับWebpack 5 Module Federation

🎉 https://github.com/alexzuza/angular-plugin-architecture-with-module-federation

เวอร์ชันก่อนหน้า

🛠️ Github สาธิตสถาปัตยกรรมเชิงมุมปลั๊กอิน

บางที Ivy อาจเปลี่ยนแปลงบางอย่างได้ แต่ในขณะนี้ฉันใช้โซลูชันที่ใช้ Angular CLI Custom Builder และตรงตามข้อกำหนดต่อไปนี้:

  • ทอท
  • หลีกเลี่ยงรหัสซ้ำ (แพ็กเกจเช่น @ angular / core {common, form, router}, rxjs, tslib)
  • ใช้ไลบรารีที่ใช้ร่วมกันในปลั๊กอินทั้งหมด แต่อย่าจัดส่งโรงงานที่สร้างขึ้นจากไลบรารีที่ใช้ร่วมกันนั้นในแต่ละปลั๊กอิน แต่ใช้รหัสไลบรารีและโรงงานซ้ำ
  • ระดับเดียวกับการเพิ่มประสิทธิภาพที่ Angular CLI มอบให้กับเรา
  • สำหรับการนำเข้าโมดูลภายนอกเราจำเป็นต้องรู้เพียงสิ่งเดียวเท่านั้นคือพา ธ ไฟล์บันเดิล
  • รหัสของเราควรรู้จักโมดูลและวางปลั๊กอินลงในหน้า
  • สนับสนุนการแสดงผลฝั่งเซิร์ฟเวอร์
  • โหลดโมดูลเมื่อจำเป็นเท่านั้น

การใช้งานทำได้ง่ายดังนี้:

ng build --project plugins --prod --modulePath=./plugin1/plugin1.module#Plugin1Module 
         --pluginName=plugin1 --sharedLibs=shared --outputPath=./src/assets/plugins

เพิ่มเติมเกี่ยวกับสิ่งนี้ในบทความของฉัน:


ตัวอย่างยอดเยี่ยม! หนึ่งคำถาม. ฉันจะส่งต่อOAuthTokenที่รันไทม์ไปยังบริการไลบรารีจากแอปหลักของเราได้อย่างไร
yogen darji

@yurzui เราสามารถใช้แนวทางเดียวกันนี้ได้หรือไม่หากเรามีแอปพลิเคชันเชิงมุมหลายตัวและเราใช้การกระจายทั้งหมดแทนที่จะสร้างโมดูลเหมือนที่คุณใช้ปลั๊กอิน 1 และปลั๊กอิน 2
Momin Shahzad

คุณจะสามารถกลับมาดูตัวอย่างนี้และทำให้ Ivy เข้ากันได้ในอนาคตอันใกล้นี้หรือไม่? หากคุณต้องการโปรดเพิ่มตัวอย่างของบริการที่ใช้ร่วมกันและการแบ่งปันInjectionTokenที่จะมีให้ใน AppModule และแทรกในปลั๊กอินอื่น ๆ ขอบคุณ!
Jyrkka

11

ฉันเพิ่งเผยแพร่บทใหม่สำหรับหนังสือ " การพัฒนาด้วย Angular " ซึ่งกล่าวถึงหัวข้อของปลั๊กอินใน Angular 2+ และน่าจะเป็นที่สนใจของผู้ที่พยายามสร้างปลั๊กอินภายนอก

ประเด็นสำคัญ:

  • ปลั๊กอิน
  • การสร้างส่วนประกอบตามชื่อสตริง
  • กำลังโหลดการกำหนดค่าจากแหล่งภายนอก
  • เปลี่ยนเส้นทางแอปพลิเคชันแบบไดนามิก
  • ปลั๊กอินภายนอก
  • การสร้างไลบรารีปลั๊กอิน
  • กำลังโหลดปลั๊กอินลงในแอปพลิเคชัน
  • เส้นทางแบบไดนามิกที่มีเนื้อหาปลั๊กอิน

หนังสือเล่มนี้รับฟรีและมีโมเดล "จ่ายตามที่คุณต้องการ" อย่าลังเลที่จะคว้าสำเนาและหวังว่าจะช่วยได้


ฉันจะแทนที่ส่วนประกอบย่อยด้วยสถาปัตยกรรมปลั๊กอินของคุณที่แสดงในหนังสือได้อย่างไร ฉันจะแทนที่เทมเพลตหรืออาจจะเพิ่ม ecc คุณสมบัติการป้อนข้อมูล ... ในขณะเดียวกันฉันก็ต้องรู้ว่ามีวิธีแทนที่ / ขยายบริการที่มีให้หรือไม่
Matteo Calò

1
@Denis Vuyka หนังสือดูดี แต่ขาดส่วนสำคัญ - สนับสนุนการรวบรวม AoT
Sergey Sokolov

7

ตัวอย่างการประยุกต์ใช้กับระบบการทำงานปลั๊กอิน (ขอบคุณสำหรับ Gijs ก่อตั้ง repo GitHub!) https://github.com/PacktPublishing/Mastering-Angular-2-Components/tree/master/angular-2-components-chapter-10ตาม บน eBook Mastering Angular 2 Components

  • สถาปัตยกรรมปลั๊กอินเพื่อขยายส่วนประกอบหลักของแอป
  • ระบบปลั๊กอินไฟล์ (เพียงแค่เพิ่มไดเร็กทอรีปลั๊กอิน / ไฟล์โดยไม่ต้องแก้ไขไฟล์กำหนดค่าหลักหรือไม่จำเป็นต้องคอมไพล์แอปพลิเคชันของคุณใหม่!)
  • โหลดและใช้ปลั๊กอินแบบไดนามิก
  • การสร้างตัวจัดการปลั๊กอินพื้นฐานเพื่อเปิดใช้งาน / ปิดการใช้งานปลั๊กอินได้ทันที

ไชโย Niklas


2
ไม่เห็นโค้ดตัวอย่างจากลิงค์นั้นโพสต์ Code Pen หรือ JSFiddle ได้ไหม
Sean Chase


4
ฉันอ่านหนังสือเล่มนี้ แต่ส่วนของปลั๊กอินล้าสมัย ใช้ JS และ SystemJS ธรรมดาในขณะที่ Angular มุ่งเป้าไปที่ typescript และ Webpack ดูเหมือนว่าใช้ Webpack และ typescript ไม่ได้ฉันโพสต์คำถามในกรณีที่คุณพบวิธีแก้ปัญหาใด ๆ นี่คือลิงค์
Luigi Dallavalle

สิ่งนี้น่าจะช่วยได้: github.com/mgechev/angular-seed/issues/…
Guillaume

มีใครยืนยันได้ไหมว่าข้างบนใช้ได้ไหม จะเป็นอย่างไรหากเราไม่ต้องการใช้ systemjs
django

5

สิ่งที่คุณกำลังมองหาคือการโหลดโมดูลที่ขี้เกียจ นี่คือตัวอย่างของมัน: http://plnkr.co/edit/FDaiDvklexT68BTaNqvE?p=preview

import {Component} from '@angular/core';
import {Router} from '@angular/router';

@Component({
  selector: 'my-app',
  template: `
    <a [routerLink]="['/']">Home</a> | 
    <a [routerLink]="['/app/home']">App Home</a> |
    <a [routerLink]="['/app/lazy']">App Lazy</a>

    <hr>
    <button (click)="addRoutes()">Add Routes</button>

    <hr>
    <router-outlet></router-outlet>
  `
})
export class App {
  loaded: boolean = false;
  constructor(private router: Router) {}

  addRoutes() {
    let routerConfig = this.router.config;

    if (!this.loaded) {
      routerConfig[1].children.push({
        path: `lazy`,
        loadChildren: 'app/lazy.module#LazyModule'
      });

      this.router.resetConfig(routerConfig);
      this.loaded = true;
    }
  }
}

ดีที่สุด ... ทอม


17
ขอขอบคุณที่สละเวลาตอบคำถามของฉัน ฉันคุ้นเคยกับโมดูลที่โหลดแบบขี้เกียจ แต่สิ่งเหล่านี้ไม่ใช่สิ่งที่ฉันกำลังมองหา ยังคงต้องทราบโมดูลที่โหลดอย่างขี้เกียจในขณะออกแบบ ฉันต้องการเพิ่มโมดูลและฟังก์ชันการทำงานจริงที่ไม่เคยมีใครรู้หรือจินตนาการมาก่อนเมื่อสร้างแอปดั้งเดิม (สิ่งที่ฉันกำลังมองหาคือสิ่งที่มีพลังมากกว่าเดิม) แน่นอนว่าส่วนประกอบเหล่านั้นจะใช้ (บางรูปแบบ) ขี้เกียจโหลด แต่มันเป็นเพียงจิ๊กซอว์ชิ้นเล็ก ๆ ชิ้นเดียว ขอบคุณอีกครั้งสำหรับการแบ่งปันคำตอบนี้
Anthony Gatlin

1
ฉันยอมรับว่านี่ไม่ได้ตอบคำถาม การโหลดแบบขี้เกียจไม่ได้ช่วยในเรื่องสถาปัตยกรรมปลั๊กอินเนื่องจากจำเป็นต้องใช้ในขณะออกแบบ เพียงแค่ไม่ดาวน์โหลด / ถ่ายโอนข้อมูลไปยังไคลเอนต์จนกว่าจะจำเป็น
โจ

จะเกิดอะไรขึ้นถ้าแอปของคุณจะรู้เกี่ยวกับปลั๊กอินที่มีอยู่ทั้งหมดในเวลาคอมไพล์ ในขณะที่คุณเพิ่มโมดูลใหม่ลงในแพลตฟอร์มจะต้องคอมไพล์ใหม่ด้วยโมดูลนี้ แค่ความคิด ... ไม่แน่ใจว่าฉันจะเพิ่มขนาดไฟล์ JS ได้อย่างมากไม่แน่ใจว่าฟีเจอร์ขี้เกียจโหลดจะใส่โมดูลดังกล่าวลงในไฟล์แยกต่างหากจากนั้นขี้เกียจโหลดฉันแค่แบ่งปันความคิดของฉัน ...
Vladimir Prudnikov

@VladimirPrudnikov หากแอปพลิเคชันสามารถรู้เกี่ยวกับปลั๊กอินทั้งหมดในเวลาคอมไพล์นั่นจะยอดเยี่ยมมาก อย่างไรก็ตามแนวคิดคือสามารถเพิ่มปลั๊กอินได้หลังจากคอมไพล์แอปพลิเคชันแล้ว สิ่งนี้จะช่วยให้สามารถเสียบโมดูลแบบไดนามิกได้อย่างแท้จริง อย่างไรก็ตามสิ่งนี้จะต้องมีการคอมไพล์โมดูลล่วงหน้าในเวลาที่ใช้งาน - และฉันไม่แน่ใจว่าจะได้ผลอย่างไร ฉันยังไม่แน่ใจว่าจะทำให้เวอร์ชันของโมดูลปลั๊กอินเข้ากันได้กับ Angular อย่างไร
Anthony Gatlin

2

ฉันทำการแฮ็คเพื่อโหลดและคอมไพล์โมดูลอื่น ๆ ในเวลาบูตสแตรป แต่ฉันไม่ได้แก้ปัญหาการอ้างอิงแบบวนรอบ

 const moduleFile: any = require(`./${app}/${app}.module`),
                    module = moduleFile[Object.keys(moduleFile)[0]];

 route.children.push({
     path: app,
     loadChildren: (): Promise<any> => module
 });
 promises.push(this.compiler.compileModuleAndAllComponentsAsync(module));

จากนั้นใน AppModule ให้เพิ่มสิ่งนี้:

{
        provide: APP_INITIALIZER,
        useFactory: AppsLoaderFactory,
        deps: [AppsLoader],
        multi: true
},

2

ฉันกำลังมองหาระบบปลั๊กอินในเชิงมุม 2/4 ด้วยสำหรับการพัฒนาสภาพแวดล้อม RAD สำหรับแอปพลิเคชันระดับองค์กรในที่ทำงาน หลังจากการวิจัยบางส่วนฉันตัดสินใจที่จะใช้คอลเลกชันของคอมโพเนนต์ pseudo-Angular ที่จัดเก็บฐานข้อมูล (แต่อาจอยู่ในระบบไฟล์)

ส่วนประกอบที่จัดเก็บในฐานข้อมูลฐานข้อมูลขึ้นอยู่กับng-dynamic และการใช้งานองค์ประกอบหลักจะคล้ายกับสิ่งนี้:

declare var ctx: any;

@Component({
    selector: 'my-template',
    template: `
<div>
    <div *dynamicComponent="template; context: { ctx: ctx };"></div>
</div>
  `,
    providers: [EmitterService],

})

export class MyTemplateComponent implements OnMount, AfterViewInit, OnChanges {


    // name
    private _name: string;
    get name(): string {
        return this._name;
    }
    @Input()
    set name(name: string) {
        this._name = name;        
        this.initTemplate();
    }

    template: string;
    ctx: any = null;

    private initTemplate() {

        this.templateSvc.getTemplate(this.name).subscribe(res => {
            // Load external JS with ctx implementation
            let promise1 = injectScript(res.pathJs);
            // Load external CCS
            let promise2 = injectScript(res.pathCss);

            Promise.all([promise1, promise2]).then(() => {

                // assign external component code
                this.ctx = ctx; //

                // sets the template
                this.template = res.template;

                this.injectServices();

                if (this.ctx && this.ctx.onInit) {
                    this.ctx.onInit();
                }

            });

        });

    }

โค้ดจาวาสคริปต์ภายนอกคล้ายกับส่วนประกอบเชิงมุม:

var ctx = {

// injected    
_httpService: {},
_emitterService: null,

// properies
model: {
    "title": "hello world!",
},


// events
onInit() {
    console.log('onInit');
},

onDestroy() {
    console.log('onDestroy');
},

onChanges(changes) {
    console.log('changes', changes);
},

customFunction1() {
    console.log('customFunction1');
},

childTemplateName: string = 'other-component'; 

};

และเทมเพลตของส่วนประกอบก็เหมือนกับเทมเพลตเชิงมุม:

<a (click)="customFunction1()">{{ ctx.model.title }}</a>
<input [(ngModel)]="ctx.model.title" type="text" />

และสามารถซ้อนกันได้ด้วย:

<a (click)="customFunction1()">{{ ctx.model.title }}</a>
<my-template [name]="childTemplateName"></my-template>

แม้ว่าจะไม่สมบูรณ์แบบ แต่ผู้พัฒนาส่วนประกอบที่กำหนดเองก็มีกรอบการทำงานที่คล้ายกันมากกว่าใน angular2 / 4


2

สามารถทำได้ "ด้วยตนเอง" เนื่องจาก webpack ไม่รู้อะไรเกี่ยวกับโมดูลภายนอก (ปลั๊กอิน) เขาจึงไม่สามารถรวมไว้ในชุดรวมได้ สิ่งที่ฉันทำคือดูรหัสที่สร้างโดย webpack และฉันพบรหัสนี้ใน main.bundle.js:

var map = {
"./dashboard/dashboard.module": ["../../../../../src/app/dashboard/dashboard.module.ts","dashboard.module"]}; 

ให้ตรวจสอบว่าอาร์เรย์นั้นมีอะไรบ้าง:

  1. "./dashboard/dashboard.module" - นี่คือการกำหนดเส้นทาง URL ของแม่มดโมดูลที่เราต้องการขี้เกียจโหลดเช่น: {path: 'dashboard', loadChildren: './dashboard/dashboard.module#DashboardModule'}
  2. "../../../../../src/app/dashboard/dashboard.module.ts" - นี่คือจุดเริ่มต้น (contructor) ใช้เวลาจาก
  3. "dashboard.module" - ชื่อไฟล์จริงที่ไม่มี chunk.js (ตัวอย่างเช่นdashboard.module.chunk.js )

ดังนั้นในทางทฤษฎีหากคุณเพิ่มรายการไปยังคุณสมบัติแผนที่กำหนดค่าการกำหนดเส้นทางของคุณและทำตามรูปแบบคุณสามารถมีระบบปลั๊กอินได้ ตอนนี้ความท้าทายคือวิธีเพิ่มหรือลบรายการจากคุณสมบัติแผนที่นั้น เห็นได้ชัดว่าไม่สามารถทำได้จากรหัสเชิงมุมควรทำสำหรับเครื่องมือภายนอก


2

ฉันพยายามใช้สถาปัตยกรรมปลั๊กอินโดยใช้ ABP, Angular และ ASP.NET Core: https://github.com/chanjunweimy/abp_plugin_with_ui

โดยพื้นฐานแล้วฉันพัฒนาปลั๊กอินเชิงมุมโดยใช้แอปพลิเคชันเชิงมุมที่แตกต่างกันจากนั้นฉันจะเพิ่มเข้าด้วยกันแบบไดนามิก

ข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ฉันบรรลุ:

ฉันมีแอปพลิเคชั่น angular-cli 2 ตัว 1 เป็นแอปพลิเคชั่น angular cli หลักและอีกตัวคือแอปพลิเคชัน cli เชิงมุมของปลั๊กอิน ปัญหาที่เรากำลังเผชิญในแนวทางสถาปัตยกรรมปลั๊กอิน Angular-cli คือวิธีที่เรารวมเข้าด้วยกัน

ตอนนี้สิ่งที่ฉันทำคือฉันเรียกใช้ ng-build บนทั้งสองแอปพลิเคชันและวางไว้ในโฟลเดอร์ "wwwroot" ซึ่งโฮสต์ในเซิร์ฟเวอร์ ASP.NET core 2.0 พื้นที่เก็บข้อมูลที่ง่ายกว่าที่แสดงแนวคิดนี้คือ Angular Multiple App: https://github.com/chanjunweimy/angular-multiple-app

abp_plugin_with_ui เป็นที่เก็บข้อมูลที่ทำงานเกี่ยวกับการพัฒนาปลั๊กอินซึ่งมีทั้งแบ็กเอนด์และ Angular cli สำหรับแบ็กเอนด์ฉันใช้เฟรมเวิร์กแอสเน็ตบอยเลอร์เพลทซึ่งส่วนหน้าได้รับการพัฒนาโดยใช้แอพพลิเคชั่น angular-cli หลายตัว

เพื่อให้แอปพลิเคชันหลักรวมเข้ากับแอปพลิเคชันปลั๊กอินเราต้องเรียกใช้ "ng-build" ทั้งสองแอปพลิเคชัน (โปรดทราบว่าเราต้องเปลี่ยนเป็น href ของแอปพลิเคชันปลั๊กอินด้วย) จากนั้นเราจึงย้ายเนื้อหาที่สร้างขึ้นของปลั๊กอิน แอปพลิเคชัน angular cli ไปยังโฟลเดอร์ "wwwroot" ของแอปพลิเคชันหลัก หลังจากบรรลุเป้าหมายทั้งหมดแล้วเราสามารถเรียกใช้ "dotnet run" เพื่อให้บริการเว็บแอปพลิเคชัน ASP.NET Core 2.0 เพื่อโฮสต์ไฟล์แบบคงที่ที่สร้างโดย "ng build"

หวังว่าจะช่วยได้ ยินดีต้อนรับทุกความคิดเห็น! ^^


ฉันกำลังพยายามทำตามเอกสารปลั๊กอินของคุณ แต่ฉันคิดว่าเอกสารกำลังข้ามไปไม่กี่ขั้นตอน ฉันขออภัยหากฉันอ่านผิด 'การเพิ่มปลั๊กอิน' ทั้งหมดไม่ชัดเจนสำหรับฉัน ฉันทำตามขั้นตอนนี้ แต่ฉันไม่เห็นผลลัพธ์จริงๆ ฉันควรเห็นอะไรในพอร์ต 4200 หลังจากเรียกใช้พาวเวอร์เชลล์ ฉันไม่เห็นโฟลเดอร์ Plugins ใน /aspnet-core/src/Todo.MainProject.Web.Host/ ฉันเรียกใช้ powershell และโฟลเดอร์นั้นไม่ได้ถูกสร้างขึ้น ความช่วยเหลือใด ๆ ที่ชื่นชม ฉันคิดว่าแนวทางของคุณคือสิ่งที่ฉันต้องการ แต่ฉันค่อนข้างคลุมเครือเกี่ยวกับวิธีการทำงาน
Brian Kitt

ตกลง. ฉันควรทำสิ่งนี้ก่อนที่จะถามคำถาม ฉันใช้เวลาในการแก้ไขข้อบกพร่องและหาคำตอบ # 1) powershell ไม่ได้ใส่. zip ในที่ที่ต้องไปฉันต้องสร้างโฟลเดอร์ปลั๊กอินแล้วย้าย zip # 2) เมื่อแอปเชิงมุมเริ่มทำงานแอปจะเรียกตัวโหลดแบบไดนามิกและคัดลอกปลั๊กอินไปยังเว็บรูท มันสะกดออกมา แต่ฉันเข้าใจแล้ว # 3) ฉันต้องใช้ url เพื่อเรียกใช้ปลั๊กอินมันไม่ปรากฏที่ใดก็ได้ ฉันคาดหวังว่ามันจะอยู่บนแดชบอร์ด ขอบคุณสำหรับการทำงานของคุณนี่เป็นส่วนสำคัญของรหัส
Brian Kitt

2

นอกประเด็นเล็กน้อย แต่ไลบรารีส่วนประกอบ UI อาจเป็นที่สนใจสำหรับผู้อ่านบางคนที่ค้นหาปลั๊กอิน:
https://medium.com/@nikolasleblanc/building-an-angular-4-component-library-with-the สามเหลี่ยม -cli-and-ng-packagr-53b2ade0701e

NativeScript มีปลั๊กอิน UI ในตัว:
https://docs.nativescript.org/plugins/building-plugins
ปลั๊กอินเหล่านั้นต้องการ Angular Wrapper:
https://docs.nativescript.org/plugins/angular-plugin


2

ขณะนี้ฉันอยู่ในภารกิจเดียวกับคุณกำลังพยายามสร้าง Angular เวอร์ชัน Pluggable / Themable และมันก็ไม่ใช่ปัญหาเล็กน้อย

จริงๆแล้วฉันพบวิธีแก้ปัญหาที่ดีงามอ่านหนังสือที่พัฒนาด้วย Angularโดย Genius Denys Vuyikaเขาอธิบายวิธีแก้ปัญหาที่ดีงามในหนังสือเล่มนี้เขาพูดถึงปลั๊กอินภายนอกในหน้า 356 ของหนังสือและใช้Rollup.jsเพื่อให้บรรลุ จากนั้นเขาจะประมวลผลเพื่อโหลดปลั๊กอินภายนอกแบบไดนามิกที่สร้างไว้ก่อนหน้านี้นอกแอปพลิเคชันของคุณ

นอกจากนี้ยังมีไลบรารี / โปรเจ็กต์อื่น ๆ อีกสองรายการที่ช่วยให้คุณบรรลุผลนี้เป็น ส่วนขยายng-packagrและNx สำหรับ Agnular (จาก Nrwl) ที่เราคาดหวังว่าจะนำไปใช้ในภายหลังและฉันจะบอกว่ามันไม่ราบรื่นอย่างที่เราคาดไว้เชิงมุมนั้นง่าย ไม่ได้สร้างมาเพื่อสิ่งนั้นดังนั้นเราจึงต้องทำความเข้าใจกับแกนกลางบางส่วนเกี่ยวกับวิธีการที่ Angular และ NX ppls เป็นหนึ่งในสิ่งที่ดีที่สุด

เราเป็นเพียงจุดเริ่มต้นของโครงการโอเพ่นซอร์สของเราเรากำลังใช้ Django + Mongo + Angular (เรากำลังเรียกWebDjangularและหนึ่งในแนวทางที่เป็นไปได้ของเราสำหรับคำตอบนี้คือ Django จะต้องเขียนไฟล์การกำหนดค่า JSON และสร้างไฟล์ ทุกครั้งที่มีการติดตั้งและเปิดใช้งานปลั๊กอินหรือธีมใหม่

สิ่งที่เราทำสำเร็จแล้วคือจากฐานข้อมูลเราสามารถใช้แท็กสำหรับส่วนประกอบต่างๆเช่นบนปลั๊กอินและส่วนประกอบจะถูกพิมพ์บนหน้าจอ! อีกครั้งโครงการอยู่ในช่วงเริ่มต้นเรากำลังใช้สถาปัตยกรรมของเราเล็กน้อยบน Wordpress และเรามีการทดสอบอีกมากมายที่ต้องทำเพื่อให้บรรลุความฝันของเรา: D

ฉันหวังว่าหนังสือจะช่วยคุณได้และการใช้ Rollup.js ฉันรู้ว่าคุณจะสามารถแก้ปัญหาที่ไม่สำคัญนี้ได้


0

ฉันพบบทความดีๆจาก Paul Ionescu เกี่ยวกับวิธีการสร้างแอปพลิเคชันที่ขยายได้ของปลั๊กอินในเชิงมุม

https://itnext.io/how-to-build-a-plugin-extensible-application-architecture-in-angular5-736890278f3f

นอกจากนี้เขายังอ้างอิงแอปพลิเคชันตัวอย่างที่ github: https://github.com/ionepaul/angular-plugin-architecture


ที่อยู่ใน Angular 5 ... Angular 9, 10 กับ Ivy ให้วิธีอื่น ๆ หรือไม่? ตัวอย่างของ Angular 5 จะยังใช้งานได้กับ Angular 9 หรือ 10 หรือไม่
mvermand
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.