Прошли те времена, когда у вашей кошки или собаки была одна
Текущее состояние
Наиболее распространенным шаблоном, используемым для современных
Типичный поток приложений SPA следует стандартным шагам:
пользователь посещает
браузер запрашивает JavaScript и CSS
приложение JavaScript запускается и добавляет начальный контент в документ браузера
пользователь взаимодействует с приложением — например, щелкает навигационную ссылку или добавляет продукт в корзину
приложение переписывает части документа браузера, чтобы отразить изменения
В большинстве случаев для достижения вышеуказанного используется фреймворк JavaScript. В таких фреймворках, как React, Vue или Angular, есть шаблоны и лучшие практики, помогающие создавать SPA. Например, React — это очень интуитивно понятная структура, использующая JSX для рендеринга контента на основе изменений пользователя и данных. Давайте рассмотрим базовый пример ниже:
//App.js
import React from «react»;
import «. /styles.css»;
const App = () => {
return (
Hello I’m a SPA 👋
) ;
}
export default App;
Это наше основное приложение. Он отображает простой вид:
import React from «react»;
import ReactDOM from «
import App from «. /App»;
const rootElement = document.getElementById («root») ;
ReactDOM.render (
,
rootElement
) ;
Затем мы запускаем приложение, визуализируя приложение React в DOM браузера. Это просто основа СПА. Отсюда мы могли бы добавить больше функций, таких как маршрутизация и общие компоненты.
SPA — основа современной разработки, но они не идеальны. СПА имеет много недостатков.
Одним из них является потеря поисковой оптимизации, так как приложение не отображается до тех пор, пока пользователь не просмотрит его в браузере. Поисковый робот Google попытается отобразить страницу, но не полностью отобразит приложение, и вы потеряете многие ключевые слова, необходимые для повышения рейтинга поиска.
Сложность фреймворка — еще один недостаток. Как упоминалось ранее, существует множество фреймворков, которые могут предоставить возможности SPA и позволить вам создать надежный SPA, но каждый из них нацелен на разные потребности, и понять, какой из них выбрать, может быть сложно.
Производительность браузера также может быть проблемой. Поскольку SPA выполняет всю визуализацию и обработку взаимодействий с пользователем, он может иметь эффект домино в зависимости от конфигурации пользователя. Не все пользователи будут запускать ваше приложение в современном браузере при высокоскоростном соединении. Уменьшение размера пакета и максимальное сокращение обработки на клиенте необходимо для обеспечения бесперебойного взаимодействия с пользователем.
Все вышеперечисленное приводит к конечной проблеме — масштабу. Чтобы создать сложное приложение, отвечающее всем потребностям пользователя, требуется несколько разработчиков. Работа над SPA может привести к тому, что многие люди будут работать над одним и тем же кодом, пытаясь внести изменения и вызвать конфликты.
Итак, каково решение всех этих проблем? Микро интерфейсы!
Что такое
Микроинтерфейс — это архитектурный шаблон для создания масштабируемого
Чтобы объяснить это подробнее, давайте возьмем пример приложения для пиццерии. Основные функции включают в себя выбор пиццы и возможность добавить ее в корзину и оформить заказ. Ниже представлен макет нашей
Макет пиццерии SPA
Давайте превратим это в микроинтерфейс, подумав о различных частях приложения, которые можно разделить. Мы можем думать об этом так же, как и о том, какие компоненты необходимы для создания нашего приложения.
SPA разбит на микрофронтенды
Все микрофронтенды начинаются с
Давайте подробнее покопаемся в «локально отделенном от основного хоста «. Когда мы думаем о традиционном SPA, в большинстве случаев вы создаете один файл JavaScript и отправляете его пользователю. С микроинтерфейсом мы отправляем пользователю только код хоста, и в зависимости от пользовательского потока мы делаем сетевые вызовы для получения дополнительного кода для остальной части приложения. Код может храниться на разных серверах от стартового хоста и обновляться в любое время. Это приводит к более продуктивным командам разработчиков.
Как создать
Существует несколько способов создания микрофронтенда. В этом примере мы будем использовать webpack. Webpack 5 выпустил федерацию модулей в качестве основной функции. Это позволяет вам импортировать удаленные сборки
Полноценное рабочее приложение
Домашний контейнер
// packages/home/webpack.config.js
const ModuleFederationPlugin = require («webpack/lib/container/ModuleFederationPlugin») ;
module.exports = {
...
plugins: [
new ModuleFederationPlugin ({
name: «home»,
library: { type: «var», name: «home» },
filename: «remoteEntry.js»,
remotes: {
«
«
},
exposes: {},
shared: require («. /package.json»).dependencies,
}),
new HtmlWebPackPlugin ({
template: «. /src/index.html»,
}),
],
};
Примечание: посмотреть webpack.config.jsфайл на GitHub можно здесь.
Здесь мы даем модулю имя «дом», так как это контейнер, содержащий все внешние интерфейсы. Затем мы предоставляем сведения о библиотеке, так как контейнер также может быть микроинтерфейсом, поэтому мы объявляем сведения о нем, такие как его тип, который в данном случае является файлом var. Тип определяет тип модуля
Затем у нас есть продукты и модули корзины, настроенные как пульты. Позже они будут использоваться при импорте и использовании компонентов. Имя, которое мы даем модулям, будет использоваться при их импорте в приложение («
После того, как мы настроим модули, мы можем добавить теги script в основной index.htmlфайл дома, которые будут указывать на размещенные модули. В нашем случае все это выполняется на локальном хосте, но в продакшене это может быть
//product list
//basket
Примечание: посмотреть index.htmlфайл на GitHub можно здесь.
Последняя часть для домашнего контейнера — это импорт и использование модулей. В нашем примере модули являются компонентами React, поэтому мы можем импортировать их с помощью React.lazy и использовать так же, как и с любыми компонентами React.
С помощью using React.lazyмы можем импортировать компоненты, но базовый код будет получен только при рендеринге компонентов. Это означает, что мы можем импортировать компоненты, даже если они не используются пользователем, и условно визуализировать их постфактум. Давайте посмотрим, как мы используем компоненты в действии:
// packages/home/src/src/App.jsx
const Products = React.lazy (() => import («
const Basket = React.lazy (() => import («
Примечание: посмотреть App.jsxфайл на GitHub можно здесь.
Ключевым отличием здесь от стандартного использования компонентов является React.lazy. Это встроенная функция React, которая обрабатывает асинхронную загрузку кода. Поскольку мы использовали React.lazyдля извлечения кода, когда он используется, нам нужно обернуть компонент в компонент Suspense. Это делает две вещи: запускает выборку кода компонента и отображает загружаемый компонент. Помимо компонента Suspense и резервного компонента, мы можем использовать наш модуль микроинтерфейса, как и любой другой компонент React.
Товар и корзина
После того, как мы настроим домашний контейнер, нам нужно настроить модули продукта и корзины. Они следуют той же схеме, что и домашний контейнер.
// packages/basket/webpack.config.js
const ModuleFederationPlugin = require («webpack/lib/container/ModuleFederationPlugin») ;
module.exports = {
...
plugins: [
new ModuleFederationPlugin ({
name: ‘basket’,
library: {
type: ‘var’, name: ‘basket’
},
filename: ‘remoteEntry.js’,
exposes: {
'. /Basket’: '. /src/Basket’
},
shared: require ('. /package.json’).dependencies
})
],
};
Примечание: посмотреть webpack.config.jsфайл на GitHub можно здесь.
Мы даем модулю имя, которое будет продуктами или корзиной и информацией о библиотеке, а затем fileName— в данном случае удаленный вход. Это стандарт для
И, наконец, в домашнем контейнере вот как вы можете использовать эти компоненты:
// packages/home/src/src/App.jsx
<React.Suspense fallback={
<ProductList
onBuyItem={onBuyItem}
/>
{
selected.length > 0 &&
<React.Suspense fallback={
<Basket
items={selected}
onClear={ () => setSelected ([]) }
/>
}
Примечание: посмотреть Product and Basket usageфайл на GitHub можно здесь.
Зависимости
Мы еще не говорили о зависимостях. Если вы заметили из приведенных выше примеров кода, каждая конфигурация модуля
Вы можете настроить общий параметр двумя способами. Первый способ — это список известных общих модулей Node, которыми вы хотите поделиться. Другой вариант — передать список зависимостей модулей из собственного
Недостатки
Все это звучит великолепно — почти слишком хорошо, чтобы быть правдой. В некоторых случаях это идеальное решение. В других случаях это может вызвать больше накладных расходов, чем того стоит. Несмотря на то, что шаблон микроинтерфейса может позволить командам лучше работать вместе и быстро продвигаться вперед в части приложения, не замедляясь
Дублированная логика зависимостей. Как упоминалось в разделе о зависимостях, webpack может обрабатывать для нас общие модули Node. Но что происходит, когда одна команда использует Lodash для своей функциональной логики, а другая использует Ramda? Теперь мы поставляем две библиотеки функционального программирования для достижения того же результата.
Сложность проектирования, развертывания и тестирования. Теперь, когда наше приложение динамически загружает контент, может быть сложнее получить полную картину всего приложения. Убедиться, что вы отслеживаете все микрофронтенды, — задача сама по себе. Развертывание может стать более рискованным, так как вы не уверены на 100%, что именно загружается в приложение во время выполнения. Это приводит к более жестким испытаниям. Каждый интерфейс можно протестировать изолированно, но для того, чтобы убедиться, что приложение работает для конечного пользователя, необходимо провести полное тестирование в реальных условиях.
Стандарты. Теперь, когда приложение разбито на более мелкие части, может быть сложно заставить всех разработчиков работать по одним и тем же стандартам. Некоторые команды могут продвинуться дальше, чем другие, и либо улучшить, либо ухудшить качество кода. Удержание всех на одной странице важно для обеспечения высококачественного взаимодействия с пользователем.
Зрелость: микрофронтенды не являются новой концепцией и были реализованы до использования iframe и пользовательских фреймворков. Тем не менее,
Вывод
Итак, мы узнали, как создать приложение React, используя федерацию модулей