Движки рендеринга

Web Host Wippy отрисовывает микрофронтенд-приложение (view.page) с помощью одного из двух движков рендеринга страниц. Движок — это вопрос доставки, выбираемый переключателем оператора, с необязательным переопределением на уровне страницы. Переносимые приложения используют API прокси и роутера Wippy, поэтому их поведение не зависит от конкретного движка.

Движок Как отрисовывается страница Изоляция Маршрутизация
Iframe (по умолчанию) srcdoc-<iframe> со вставленным proxy.js Полная изоляция документа Только memory-history (у srcdoc нет реального URL)
Web Fragment Same-origin-реалм reframed, отражённый в shadow root <web-fragment>, с proxy-fragment.js Изоляция реалма, общее дерево DOM Настоящая window.history (работают URL-роутеры)

Оба движка предоставляют одни и те же сервисы приложения Wippy: аутентифицированный API, WebSocket, опосредованное хостом состояние, диалоги confirm/bridge, события @history/@visibility, распространение заголовка, глобальный перехват ошибок, инъекцию CSS хоста и темы (включая тёмную тему в shadow DOM), авто-высоту в content-режиме и вложенные встраивания <w-artifact>. Их возможности по работе с историей браузера намеренно различаются, как показано в таблице.

Для приложения, способного работать под любым движком, используйте createAppRouter() из @wippy-fe/router. Текущая фабрика использует memory history, получает начальный маршрут из AppConfig.context.route и синхронизируется с хостом через @history. Роутер с прямым createWebHistory() работает только с Fragment и непереносим на развёртывания iframe или auto, которые могут откатиться к iframe.

Как отрисовывается фрагмент

view.page, выбранная для движка fragment, монтируется как <web-fragment src="/@fragment/{id}/">. Шлюз /@fragment в wippy/views обслуживает контракт reframing; клиент reframed создаёт скрытый same-origin-iframe реалма (wf:<id>), стримит преобразованный шлюзом HTML в shadow root фрагмента и запускает proxy-fragment.js (адаптер @wippy-fe/proxy) внутри реалма, чтобы предоставить API прокси $W. Поскольку реалм same-origin с хостом, прокси общается с хостом напрямую, а не через postMessage.

Та же страница под движком iframe — это srcdoc-<iframe> со вставленным proxy.js — см. Прокси и изоляция.

Выбор движка

Глобальный переключатель (оператор)

Движок для всего развёртывания задаётся требованием фасада render_enginehostConfig.renderEngine. По умолчанию — iframe; только точная строка fragment переводит развёртывание на движок fragment (любое другое значение, включая опечатку, трактуется как iframe).

wippy run -c -o wippy.facade:render_engine:default=fragment

Параметр см. в Фасад → Движок рендеринга.

Переопределение на уровне страницы (автор приложения)

Страница включается или исключается через wippy.renderEngine в блоке wippy своего package.json:

Значение Поведение
"auto" (по умолчанию) Следовать глобальному переключателю.
"iframe" Всегда отрисовывать как srcdoc-iframe — отказ от фрагментов независимо от переключателя.
"fragment" Предпочитать движок fragment. При глобальном развёртывании fragment: всегда. При глобальном развёртывании iframe: только если рантайм-проба возможностей (GET /@fragment/{id}/, кэшируется на сессию) подтвердит наличие шлюза и прокси; иначе — безопасный откат к iframe.

См. Микрофронтенд-приложения → Движок рендеринга.

Ограничения фрагментов

Некоторые браузерные API ведут себя неверно — и молча — внутри reframed-реалма. Страница, зависящая от любого из них, должна зафиксировать wippy.renderEngine: "iframe".

API / возможность Поведение в реалме Последствия
document.elementFromPoint Возвращает nullнезависимо от размера панели Ломает hit-тестирование указателя: drag & drop, сортируемые списки, Popper/floating-ui, виртуальные скроллеры
matchMedia, единицы vh/vw, position: fixed Разрешаются относительно viewport хоста, а не панели фрагмента Отклонение примерно на 1px в полноразмерной панели; существенно неверно в маленькой панели (боковая панель/модальное окно)
window.scrollX/Y, scrollTo Нацелены на скрытое окно реалма (всегда 0) Интерфейс, управляемый прокруткой, читает неверную геометрию
Web Workers, Canvas, WebGL, WASM Работают нормально

vh/vw и matchMedia попали сюда потому, что спрашивают об окне. Приложение, которое вместо этого рассчитывает размеры относительно выделенного ему surface — container-запросы к wippy-surface и переменные --wippy-surface-* — разрешается одинаково под обоими движками и не нуждается в фиксации. См. Переносимость surface, а для преобразования существующего приложения — Миграция surface. У position: fixed и elementFromPoint переносимой формы нет, и они остаются настоящими причинами для фиксации.

Два детектора выявляют это на этапе разработки (они обнаруживают несовместимость кода приложения, а не ошибки развёртывания):

  • Во время сборки (@wippy-fe/vite-plugin): сканирует исходный код страницы и выдаёт предупреждение сборки с названием API и рекомендацией wippy.renderEngine: "iframe".
  • Во время выполнения в dev (прокси фрагмента, только DEV): патчит эти API, чтобы один раз выдать console.warn при фактическом вызове.

Включение фрагментов — краткая настройка

Включение движка fragment в потребляющем приложении требует актуальных модулей фреймворка плюс переключателя оператора — без обвязки роутера или параметров:

  1. Модули фреймворка — используйте актуальную совместимую пару wippy/facade и wippy/views, предоставляющую переключатель render_engine и самомонтирующийся шлюз фрагментов. Точный релиз уточняйте в актуальной документации модулей Wippy.
  2. Переключатель — установите render_engine фасада в fragment (глобально) либо включайте страницы по одной через wippy.renderEngine.

Шлюз /@fragment предоставляется самим актуальным wippy/views: модуль объявляет собственный роутер верхнего уровня и привязывает его к требованию server со значением по умолчанию app:gateway. Потребителю не нужна никакая обвязка фрагментов, и он нормально загружается на движке iframe независимо от того, включены фрагменты или нет; переопределяйте параметр server, только если идентификатор вашего http.service отличается от app:gateway. Когда страница включает фрагменты для себя в развёртывании, в остальном работающем на iframe, рантайм-проба возможностей подтверждает наличие шлюза и proxy-fragment.js перед переключением и иначе остаётся на движке iframe. Глобальный переключатель render_engine: fragment доверяет оператору и пробу не выполняет. См. Views → Шлюз Web Fragments.

Самому фронтенд-приложению не нужен специфичный для фрагментов код; proxy-fragment.js — артефакт хоста, раздаваемый с CDN, а не то, что приложение включает в свой бандл.

Смотрите также