Движки рендеринга
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_engine → hostConfig.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 в потребляющем приложении требует актуальных модулей фреймворка плюс переключателя оператора — без обвязки роутера или параметров:
- Модули фреймворка — используйте актуальную совместимую пару
wippy/facadeиwippy/views, предоставляющую переключательrender_engineи самомонтирующийся шлюз фрагментов. Точный релиз уточняйте в актуальной документации модулей Wippy. - Переключатель — установите
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, а не то, что приложение включает в свой бандл.
Смотрите также
- Фасад — переключатель оператора
render_engineиhostConfig.renderEngine - Views — самомонтирующийся шлюз
/@fragmentи его привязкаserver - Микрофронтенд-приложения (view.page) — поле
wippy.renderEngineна уровне страницы - Прокси и изоляция — общий API прокси (оба движка) и движок iframe
- Обзор Web Host — как хост загружает и отрисовывает страницы