Створення розширюваної динамічної підключається корпоративної програми з Angular

У цій статті ми поговоримо про те, як ми можемо використовувати інструменти побудови Angular CLI для створення попередньо скомпільованого модуля Angular, який може спільно використовувати спільний код з іншими плагінами і навіть працювати з Angular universal. Це неофіційне рішення, але воно добре працює для нашого випадку.

динамічного

AngularInDepth віддаляється від Середнього. Останні статті розміщені на новій платформі inDepth.dev . Дякуємо за участь у поглибленому русі!

Ось просте зображення того, що ми будуємо:

Тут ми маємо просту сторінку, де ми отримуємо конфігурацію плагінів із файлу plugins-config.json. Тоді ми спочатку ліниво завантажуємо скомпільований плагін AOT (plugin1.js), який має залежність від shared.js. Спільна бібліотека містить компонент Tabs та Tabs ng factory. Через деякий час ми завантажуємо другий плагін (plugin2.js), який повторно використовує код із раніше завантаженої бібліотеки shared.js.

Ось сховище архітектури angular-plugin Github, якщо ви хочете поглянути на вихідний код.

В демонстрації ми використовуємо Angular CLI 7.3.6

Давайте не чекатимемо Айві, а натомість матимемо справу з поточним ViewEngine сьогодні

  • Чому саме кутовий?
  • Мета
  • Що таке плагін?
  • Чому так складно створити плагін за допомогою Angular?
  • Вимоги
  • Інші рішення
  • На шляху до рішення
  • Одинарна пачка
  • Зовнішні
  • Динамічний експорт
  • Створення плагіна
  • Зовнішні та спільні кутові бібліотеки
  • Завантажити плагін (клієнт, сервер)
  • Як відобразити плагін?
  • Як ізолювати основну програму від помилок у плагіні?

Команда Angular та громада продовжують стрімке зростання своєї екосистеми.

Angular допомагає нам послідовно структурувати наш код, щоб кожен новий розробник міг легко брати участь у проекті.

Нам подобається той факт, що ми дотримуємося найкращих веб-практик з Angular, просто подумайте про машинопис, спостережувані дані, візуалізацію на стороні сервера, веб-працівників, диференціальне завантаження, прогресивне веб-додаток (PWA), ледаче завантаження тощо. швидко застосувати ці функції.

Також є більше функцій, які пропонує нам Angular, такі як вбудована система впорскування залежностей, реактивні форми, схеми тощо.

Ось чому ми зазвичай обираємо Angular при побудові корпоративного додатка.

Одного разу наш клієнт попросив нас додати нову функцію до його існуючої програми Angular Universal. Він хотів мати роз’ємну систему управління вмістом (CMS). Метою було додати можливість розширити функціональність поточної програми, щоб сторонній розробник міг легко самостійно розробити новий модуль та завантажити його. Потім додаток Angular повинен забрати його без необхідності перекомпілювати цілу програму та передислокувати.

Простіше кажучи, нам потрібно розробити систему плагінів.

Системи плагінів дозволяють розширити програму без зміни основного коду програми.

Це звучить просто, але писати плагін за допомогою Angular - це завжди проблема.

Один з моїх колег, який давно працював з AngularJS, сказав, що бачив додаток Angular 2, написане простим es5 (хм ... можливо, він знайшов мій jsfiddle або моє старе репо). Тож він запропонував створити модуль Angular в es5, помістити його в папку, і головний додаток повинен якось працювати.

Не зрозумійте мене неправильно, але я з Angular, оскільки 2 alpha та Angular 2 (або просто Angular) - це абсолютно нова річ.

Звичайно, головна помилка тут - компіляція Ahead Of Time (AOT). Основною перевагою використання AOT є краща продуктивність вашої програми.

Я бачив багато прикладів, які використовують JitCompiler для побудови підключається архітектури. Це не той шлях, яким ми хочемо піти. Ми повинні тримати наш додаток швидко і не включати код компілятора в основний пакет. Ось чому ми не повинні використовувати es5, оскільки лише код TypeScript може бути попередньо скомпільований. Крім того, поточна реалізація Angular AOT базується на перехідній області @NgModule і вимагає, щоб усі були скомпільовані разом. Все це ускладнює ситуацію.

Ще одна помилка - нам потрібно ділити код між плагінами, щоб уникнути дублювання коду. Яке дублювання ми можемо розглянути? Ми розрізняємо два типи коду, який можна дублювати:

  • Код, який ми пишемо, або код, який ми беремо з node_modules
  • Код, створений AOT, згадайте про заводи компонентів та модулів (component.ngfactory.js та module.ngfactory.js). Насправді це величезна кількість коду.

Щоб уникнути дублювання коду, нам потрібно мати справу з тим, як ViewEngine створює завод.

Якщо ви не знаєте, ViewEngine - це поточний механізм візуалізації Angular

Проблема тут полягає в тому, що код, згенерований компілятором Angular, може вказувати на ViewFactory з іншого шматка згенерованого коду. Наприклад, ось як визначення елемента пов’язане з ViewDefinitionFactory (вихідний код Github)

Отже, це призводить до отримання дублікатів усіх заводів із загальної бібліотеки.

Отже, коли ми обговорювали систему плагінів Angular, нам слід мати на увазі наступне:

  • АОТ
  • Уникайте дублювання коду (пакети, такі як @ angular/core, rxjs, tslib)
  • Використовуйте спільну бібліотеку у всіх плагінах. Але, НЕ ДОСТАВЛЯЙТЕ згенеровані заводи з цієї спільної бібліотеки в кожному плагіні. Швидше, повторно використовуйте бібліотечний код та фабрики.
  • Для імпорту зовнішніх модулів нам просто потрібно знати одне: їх шлях до файлу пакета.
  • Наш код повинен розпізнати модуль і розмістити плагін на сторінці.
  • Підтримка візуалізації на стороні сервера
  • Завантажуйте модуль лише за потреби
  • Підтримуйте той самий рівень оптимізації, який дає нам Angular CLI

Усі ці міркування привели нас до нашого власного рішення.

Існують різні підходи, але їм не вистачає найважливіших частин: підтримка AOT, оптимізований код та недубльований код.

І одне із рішень, яке є близьким до наших потреб, це: https://github.com/iwnow/angular-plugin-example

Він використовує зведення для створення пакета плагінів у форматі umd.

Однак ось недоліки, які я бачу при такому підході:

  • ❌ він не використовує методи оптимізації, які пропонує нам Angular CLI: тобто він не видаляє декоратори Angular і не запускає buildOptimizer.
  • ❌ він дублює заводи, якщо ми використовуємо спільні компоненти в кожному плагіні.

На щастя, Angular дуже розширюється за допомогою власних сценаріїв.

Починаючи з Angular 6, існує можливість зачепити процес компіляції за допомогою конструкторів. Це дозволяє нам додати власну конфігурацію веб-пакета, включаючи всі переваги, які ви можете собі уявити від налаштування ванільного веб-пакета.

Тому я подумав, що може бути непоганою ідеєю написати власний конструктор для побудови плагінів.

Angular CLI підтримує створення бібліотек. Але ng-Packagr, який використовується для побудови цієї бібліотеки, генерує багато артефактів, які нам не потрібні. (Так, я знаю, що він відповідає формату Angular Package (APF)). І ці артефакти можуть споживати лише інші кутові програми.

І тут я подумав, що можу використати програму Angular для створення своїх плагінів. Під програмою я маю на увазі програму, яка генерується за допомогою команди CLI, такої як ng generate application. Цей підхід є вигідним, оскільки він дає нам такий самий рівень оптимізації, як і Angular CLI. Наприклад, ми не отримаємо декоративні декоратори Angular після AOT.