@cxra/routine-assistance v0.1.6
@cxra/routine-assistance
Pipes
isD
checks if the value is defined
isND
checks if the value is undefined or null
asSanitizedHtml
is meant to be sanitized to declarative html for use in a template
@cxra/module-federation-navigator
Данная библиотека, предназначена:
- To make it a little easier to work with Module Federation in basic cases.
- Автоматизировать не только управление модулями через файл конфигурации, но и управление навигацией к этим модулям и доступностью их для разных контекстов исполнения. Данная потребность возникала: В продуктовой разработке когда один продукт разворачивается для разных заказчиков с разной конфигурациеи. Когда нужно предоставить возможность devops быстро отключать, включать и конфигурировать состав.
- Сохранить возможность ленивой загрузки и при этом дать возможность самим модулям предоставлять компонент который будет использован в качестве навигационного элемента
Конфигурирование
Основные настройки описываются в конфигурационном файле манифеста модулей {manifest_name}.json
для изменения конфигурации после развертывания.
- Рекомендуемым местом расположения файла конфигурации для проектов где основное приложение написано на angular является
.\{app-name}\src\assets\{manifest_name}.json
для публикации стандартными средствами - Так же регулярным вариантом использования является сборка и предоставления манифеста server-side в виде ответа на запрос, так как формат данных манифеста
json
Recommended point to load the configuration is to implement the standard angular app init loop, by provide APP_INITIALIZER
providers: [{
provide: APP_INITIALIZER,
useFactory: (manifest: CXraModuleNavigatorManifest<cxra.module.federation.navigation.NavigableRemoteModuleConfig>) =>
(): Promise<void> =>
manifest.load('/assets/modules.manifest.json'),
deps: [CXraModuleNavigatorManifest],
multi: true
}],
Настройка источников модулей
Данная библиотека основана на angular-architects/module-federation-plugin, по этому основными видами потребляемых модулей являются:
Модули
angular
. В качествеtype
указывается значение module.``` "module-a": { "type": "module" "remoteEntry": "http://localhost:3000/remoteEntry.js" "remoteName": "example-module-a" "exposedModule": "./Module" "elementName": "AppModule" ... } ``` `elementName` наименование основного класса публикуемого как angular module. В частности пример приведенный выше, справедлив для внешнего модуль публикованного следующим образом ``` name: "example-module-a" exposes: { "./Module": "./examples/example-module-a/src/app/app.module.ts" "./Component": "./examples/example-module-a/src/app/components/nav/nav.component.ts" } ```
Скрипты
js
. В качествеtype
указывается значение script.``` "react-a": { "type": "script" "remoteEntry": "https://witty-wave-0a695f710.azurestaticapps.net/remoteEntry.js" "remoteName": "react" "exposedModule": "./web-components" "elementName": "react-element" } ``` `elementName` наименование component получаемого из публикации в качестве root.
Общие настройки вне зависимости от типа:
remoteEntry
публичный адрес размещения сгенерированного файла декларации интегрируемых модулей.
remoteName
наименование remote object используемое для публикации.
exposedModule
наименование секции размещения модуля в экспозиции.
Настройка навигации модуля
На базовом уровне навигация определяется свойством navigation
.
Для модуля может быть определено поведение без навигационного элемента.
Данное решение может быть применимо в случаях когда функциональность remote модуля должна быть доступна только из определенного блока интерфейса или как звено определенного бизнес сценария. Такой подход реализуется по средствам доступа по конкретному маршруту. `navigation` задается непосредственно строкой описывающей route. ``` "navigation": "module-a/offers/:id/accepted" ```
Для модуля может быть определена глобальная навигация.
Данное решение предоставляет возможность самому модулю запубликовать навигационный элемент, `component` который будет использован для отображения в меню, инвертировав данную зависимость из основного приложения. Или напрямую в конфигурационном файле определить `template` который будет использоваться в качестве навигационного элемента, что позволяет интегрироваться с remote module не публикующему навигационный элемент, например если он legacy или поставляется сторонним разработчиком. `navigation` задается объектом содержащим ряд конфигураций. ``` "navigation": { "route": { "path": "module-a" }, "component": { "type": "ModuleANavComponent", "remoteEntry": "http://localhost:3000/remoteEntry.js", "exposedModule": "./Component" } } ``` * `route` описание route для lazy load сборки модуля * `path` обязательная характеристика задающая строкой route * `params` карта path параметров (_optional_) * `queries` карта условных параметров (_optional_) * `component` описание элемента для представления в навигации * Может быть представлен конфигурацией использующей remote `component` и в данном случае описывается радом свойств. * `type` название класса компонента из remote модуля который будет использоваться в качестве навигационного элемента ⚠️ Рекомендуется оформлять как __standalone__ компонент ``` @Component({ selector: 'module-a-nav' standalone: true ... }) export class ModuleANavComponent {} ``` * `remoteEntry` публичный адрес размещения сгенерированного файла декларации модуля содержащего навигационный элемент. * `exposedModule` наименование секции размещения навигационного элемента в экспозиции. ``` exposes: { "./Module": "./examples/example-module-a/src/app/app.module.ts" "./Component": "./examples/example-module-a/src/app/components/nav/nav.component.ts" } ``` * Может быть представлен конфигурацией использующей `template` В данном случае описывается текстовым представлением шаблона напрямую в конфигурационном файле. И предоставляет возможность задания индивидуального значения каждому экземпляру развертывания силами devops. ``` "component": "<span>to <b>reAct-B</b></span>" ```
Управление доступностью навигации к модулю, в зависимости от контекста или состояния
В конфигурационном файле манифеста модулей {manifest_name}.json
активность модуля и его навигации, может быть установлена в три состояния 'on' | 'off' | 'promise'.
"module-b": {
"state": "on | off | promise"
...
}
...
on
- модуль активен сразу и будет доступен сразу после загрузки инициированной активацией маршрутаoff
- навигация к модулю не будет доступна и маршруты для активации модуля не будут опубликованыpromise
- навигация к модулю будет разблокировано если будет найдено и выполнено положительно обещание активации, публикуемое по token в DI``` providers: [{ provide: CXRA_MODULE_OPTIONS, useFactory: (_http: HttpClient) => ({ ['module-a']: { state: new Promise<boolean>((resolve) => { _http.get<...>(...).pipe( map(user => user.permissions.has(...)), ... takeUntil(...) ).subscribe(() => resolve(true)); }) } }), deps: [HttpClient], multi: true }, ...], ```
@see cxra.module.federation.navigation.RemoteModuleState
Публикация пользовательских событий модуля
Для публикации реализации возможности отображения факта наличия ии самих пользовательских уведомлений remote module в навигационной части приложения в едином стиле, предусмотрена возможность опубликовать источник событий через контракт CXRA_MODULE_OPTIONS как в непосредственном модуле, так и в локализованном приложении потребителе. Тем самым инвертированная устранив зависимость на предоставление модулю интерфейсов для непосредственного размещения элементов в обобщенной части интерфейса приложения.
Для каждого модуля имеющего оповещения в его секции публикуется:
events
- представляющий реализацию Observable<Array>``` providers: [{ provide: CXRA_MODULE_OPTIONS, useFactory: (...) => ({ ['module-a']: { ... events: new BehaviorSubject<unknown>(...) } }), deps: [...], multi: true }] ```
Общие настройки
Для задания общих настроек навигации и менеджмента remote modules определен контракт CXRA_MODULE_NAVIGATOR_OPTIONS обладающий рядом характеристик.
undefined.component
предназначена для определения компонента который будет использован в случае перехода к неопределенному элементу маршрутизации, в случае необходимости задания такого поведения централизовано``` providers: [{ provide: CXRA_MODULE_NAVIGATOR_OPTIONS, useValue: { undefined: { component: UnfoundComponent } } }], ```
Examples
This repository provides examples of an application using this approach.
Description | Project |
---|---|
Контекст. Пример проекта используемого для публикации и обработки данных используемых между разными модулями. | examples\example-context |
Module A. С примером отключения навигации модуля из самого себя. | examples\example-module-a |
Module B. С примером инкапсуляции внутренних стилей и данных внешнего контекста. | examples\example-module-b |
Directly the application publishes different modules and navigation. | examples\example-app |
First run
Install packages:
yarn install
Please note, you **must** use **yarn** during the beta phase of CLI 11 b/c it allows to override dependencies to force the CLI into webpack 5.
Build lib`s
Navigator: ``yarn build:module-federation-navigator``
Usage
- Start all micro-frontend's and app:
yarn start:example:navigator:all