предисловие
Наша команда работает над системой XX, стек технологийReactВ настоящее время система становится большей и большей, затраты на разработку и обслуживание увеличиваются, и весь проект должен быть упакован каждый раз, что является трудоемким и трудоемким трудоемким. После рассмотрения было решено разделить его в несколько проектов и объединить их в полную систему. Архитектура Micro-Frontend является очень хорошим выбором.
Микрофронтенды имеют следующие преимущества:
- Обслуживание одного проекта: например,
商品模块Вытащенный для формирования проекта, он может поддерживаться командой в одиночку, достигая хорошей развязки - Уменьшенная сложность: нет необходимости разрабатывать во всей интегрированной огромной системе, избегая огромного количества кода, быстрой компиляции во время разработки и повышения эффективности разработки.
- Отказоустойчивость: ошибка в одном проекте не влияет на всю систему
- Гибкий технологический стек: можно использовать vue, react, angular и т. д., включая другие интерфейсные технологические стеки, и тем, кто знает vue, не нужно заново учиться реагировать
Самым большим преимуществом для нас является单项目维护.
экспонат
Пример схемы пользовательского интерфейса
Делим весь микрофронтенд на две части:
- Основной проект (Main): Часть красного поля, как родитель всего проекта, отвечает за отображение модуля меню и модуля заголовка.
- Подприложения: часть синего поля, роль подпроекта заключается в отображении конкретного бизнеса.
Анимированный дисплей
Наблюдайте за изменением адресной строки, который содержит/app1/xxxа также/app2/xxx, который на первый взгляд является переключением между двумя страницами в проекте, на самом делеиз двух отдельных проектов, app1 и app2 из разных репозиториев git.
Диаграмма микроинтерфейсной архитектуры
Весь процесс примерно таков: пользователь обращается к index.html, затем запускает загрузчик модулей Js, загрузчик регистрирует каждый проект в соответствии с конфигурационным файлом (project.config) всей системы, система сначала загружает основной проект (основной), а затем будет динамически загружать соответствующие подпроекты в соответствии с префиксом маршрутизации
Наша архитектура также ссылается на множество хороших статей в Интернете, из которых можно сослаться на основные статьи.Арири Специальности/архив/110…
О проекте.config
примерно так
[
{
isBase: false,
name: 'app1',
version: '1.0.0',
//通过该路由前缀匹配加载当前入口文件
hashPrefix: '/app1',
//入口文件
entry: 'http://www.xxxx.com/app1/dist/singleSpaEntry.js',
//顶级Store
store: 'http://www.xxxx.com/main/dist/store.js'
}
......
]
Здесь project.config используется в производственной среде.Мы загружаем упакованные файлы в OSS (или CDN), а затем синхронизируем текущую упакованную конфигурацию проекта с сервером.Сервер интегрирует все конфигурации проекта в project.config.При доступе к индексу .html, будет получен project.config, а затем single-spa зарегистрируется по этим конфигурациям и загрузит соответствующий проект по маршруту.
Технические подробности
single-spa
Мы нашли несколько репозиториев, реализующих микрофронтенды, и после сравнения решили их использовать.single-spa.
Наш технологический стек — реакция, и нам нужно использовать single-spa-react для создания записи подпроекта Код ключа выглядит следующим образом:
import singleSpaReact from 'single-spa-react';
const reactLifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: Root,
domElementGetter
});
export function bootstrap(props) {
return reactLifecycles.bootstrap(props);
}
export function mount(props) {
return reactLifecycles.mount(props);
}
export function unmount(props) {
return reactLifecycles.unmount(props);
}
Если вы используете vue, вы можете использовать single-spa-vue
Затем в системном файле входа прописать все проекты:
import * as singleSpa from 'single-spa';
singleSpa.registerApplication(
'app1',
() => SystemJS.import('app1-entry.js'),
() => location.hash.startsWith(`#/app1`),
props
);
Подробную информацию можно найти на официальном сайте single-spa.single-spa.js.orgЗдесь много примеров
Webpack и SystemJs
Мы используемlernaУнифицированное управление пакетами зависимостей всех проектов и унифицированные версии всех зависимых пакетов, что очень удобно для обслуживания.
Используйте функцию dll webpack для извлечения общих зависимостей всех проектов, таких как react, react-dom, react-router, mobx и т.д.
Чтобы облегчить динамическую загрузку проекта, мы также обращаемся к идеям онлайн-боссов и используемsystemjs, мы используем версию 0.20.19. С systemjs вам нужно изменить libraryTarget в Webpack:
output: {
publicPath: 'http://www.xxxxx.com/',
filename: '[name].js',
chunkFilename: '[name].[chunkhash:8].js',
path: path.resolve(__dirname, 'release'),
libraryTarget: 'amd', //注意 这里使用 amd 的规范
library: 'app1'
},
Мы не использовалиumdспецификация, использованиеamdспецификация и не использует карты импорта в systemjs
функция, но напрямую через project.config для динамической загрузки записи модуля.
связь между приложениями
По этому поводу я тоже видел планы некоторых больших парней.Наверное во всех проектах есть стор.При регистрации записи все сторы ставятся в очередь.Когда нужно обновить состояние в сторе, вызывается диспетчеризация синхронизировать все магазины.
Мой подход такой же, как и для традиционного одностраничного приложения. В системе должен быть только один Магазин верхнего уровня. Поскольку Магазин верхнего уровня обычно хранит общее состояние всей системы, такое как меню, информация о пользователе и т. д., Ставлю в Основной проект, но при упаковке This Store извлекается отдельно:
entry: {
singleSpaEntry: './src/singleSpaEntry.js',
store: './src/store' //单独一个入口
},
При регистрации передайте этот Store в каждый проект:
//顶级Store
const mainStore = await SystemJS.import(storeURL);
singleSpa.registerApplication(
'app1',
() => SystemJS.import('http://www.x.com/app1/entry.js'),
hashPrefix('/app1'),
{ mainStore }
);
singleSpa.registerApplication(
'app2',
() => SystemJS.import('http://www.x.com/app2/entry.js'),
hashPrefix('/app1'),
{ mainStore }
);
Таким образом можно управлять только этим магазином, что очень удобно. Примечание. Я использую Mobx для управления состоянием.
Интерфейсное развертывание
Способ развертывания очень прост. Я сам написал плагин веб-пакета, чтобы передать упакованный дистрибутив в OSS, а затем отправить конфигурацию проекта на сервер. Сервер (NodeJs) организует project.config в соответствии с поступающей конфигурацией проекта. Затем пользователь получит project.config при доступе к index.html.В это время single-spa регистрирует все проекты в соответствии с конфигурацией, а затем извлекает соответствующий файл записи проекта js файл в соответствии с маршрутом.
Поместите смонтированный DOM подпроекта в основной проект
Наше требование состоит в том, чтобы Main был Layout всего проекта, а mount Dom подпроекта тоже был в Main проекте, это значит, что подпроекты не могут быть смонтированы до полного рендеринга Main проекта. Я сослался на реализацию некоторых микрофронтендов в интернете, и позаимствовал метод domElementGetter:
function domElementGetter() {
let el = document.getElementById('sub-module-wrap');
if (!el) {
el = document.createElement('div');
el.id = 'sub-module-wrap';
}
let timer = null;
timer = setInterval(() => {
if (document.querySelector('#content-wrap')) {
document.querySelector('#content-wrap').appendChild(el);
clearInterval(timer);
}
}, 100);
return el;
}
demo
демонстрационный адрес:GitHub.com/viand/m признает…Эта демонстрация предоставляет только справку на микроконце, фактическую разработку и развертывание, вам нужно увидеть вас
заключительные замечания
Это первый раз, когда мы играли с микро-интерфейсом, может быть много недостатков, я надеюсь, что вы будете терпеть меня.