В примере DDG много ~магии~ в вызове MicroFrontendRegistry.call()
, который фактически обеспечивает успешное обращение к конечной точке DDG. Так что давайте немного разберемся с магией.
Решение о том, как построить абстракцию
Поскольку мы так много работаем с веб-компонентами и глобалом window.customElements
, который делает реестр возможным для фронтенда, я решил немного отзеркалить его при построении параллельной концепции для конечных точек микросервисов.
- источник для MFR
- определение сервисов
- npm
MicroFrontendRegistry
состоит в основном из:
- предоставление интерфейса singleton, чтобы существовал только один реестр, независимо от того, кто его объявляет
- сделать его доступным для запросов через DOMor или прямой доступ к окну (личное предпочтение, я всегда пишу свои синглтоны таким образом).
Определение сервиса
Поскольку я всегда стараюсь выбрать максимальное повторное использование в различных контекстах, я не предполагал, что это единственный проект, в котором я когда-либо буду использовать эти микросервисы. Я также не хочу предполагать, что эти сервисы никогда не будут конфликтовать или что вы всегда захотите иметь @core/whatever
в качестве сервиса в вашем проекте.
В результате у нас есть сервисы, сгруппированные в группы сервисов, которые могут быть определены с помощью отдельных вызовов. В данный момент у нас есть три группы, которые можно легко включить в качестве ярлыка для их использования.
import { enableServices } from '@lrnwebcomponents/micro-frontend-registry/lib/microServices.js';
// then enable the service groups in question
enableServices(['core', 'experimental', 'haxcms']);
- основные — сервисы, которые являются общими / ожидаемыми / простыми
- экспериментальные — те, с которыми можно поиграть / которые будут рассмотрены в будущем
- haxcms — специфичные для приложения вещи для haxcms.
Опять же, это просто быстро добавит целую кучу сервисов, но давайте вернемся к примеру с duck duck go, как класс middleware узнает, что вызывать и где это находится.
DDG регистрация микросервиса
// duckDuckGo
MicroFrontendRegistry.add(
{
endpoint: '/api/services/website/duckDuckGo',
name: '@core/duckDuckGo',
title: 'Duck Duck Go',
description: 'Search results from duck duck go',
params: {
q: "query param to search on"
}
}
);
Здесь мы видим, что у нас есть конечная точка и имя. Название, описание и параметры в основном нужны разработчикам / если мы когда-нибудь решим визуализировать эту информацию. В случае DDG все, что мы делаем, это передаем параметр запроса q
, и мы получим вызов конечной точки и возвращение нашего json
блоба результатов. Эта простая ассоциация конечной точки с именем позволит нам впоследствии менять и перемещать имя конечной точки при необходимости.
А… а когда это нужно?
Забавно, что вы спросили! Вот как выглядит следующее определение после DDG:
// screenshot - kept by itself bc of size of getBrowserInstance
MicroFrontendRegistry.add({
endpoint: "https://screenshoturl.elmsln.vercel.app/api/screenshotUrl",
name: "@core/screenshotUrl",
title: "Screenshot page",
description: "Takes screenshot of a URL and returns image",
params: {
urlToCapture: "full url with https",
quality: "Optional image quality parameter"
}
});
😺 — Я создаю службу скриншотов локально в vercel
😖 — Я в продакшене пытаюсь вызвать его.
В данном случае причина была в том, что наш screenshotUrl
использует puppeteer
— удивительную, но тяжелую (вес файла) библиотеку для запуска Chrome и других браузеров без головы. В результате ограничений лямбда AWS (на которой работает Vercel) наш монореп не мог запустить puppeteer вместе со всем остальным.
В результате наши пути должны были измениться, поскольку мы перенесли эту функциональность в собственный репозиторий (и таким образом она могла собираться независимо и работать без ограничений на размер файлов!) Чтобы внести это изменение, я заменил оригинальную конечную точку: "/api/media/web/screenshot" на полный URL-адрес производственного пути. Однако все места, где мы вызывали
@core/screenshotUrl`, не изменились!
Следуя методологии npm
-esk для именования, мы можем расширить то, как мы будем называть их в будущем, красиво распределить пространства имен и дать соглашение, к которому люди привыкли, без прямой ссылки на URL, которые могут измениться или должны быть перемещены в будущем.
Другие причины для перемещения менее интересны; например, переименование, рефакторинг и т.д.
Видео, в котором рассказывается об этих трех статьях
Вот видео, в котором подробно рассматривается код и структуры вызовов, чтобы DDG работал от конца до конца.