Skip to content

Ваш модуль в оболочке песочницы

Ваш модуль — это remote федерации. По-настоящему он работает только тогда, когда его загружает оболочка, и для вашего модуля это оболочка песочницы: тот же образ Building OS, развёрнутый отдельно и привязанный к вашей песочнице. В продуктивную оболочку ваш модуль не попадает никогда: код модуля выполняется с полным доверием той оболочки, которая его загрузила, поэтому стороннему коду выделяется собственная.

Начиная с 1.14.0

tv-sdk sandbox install и скрипты dev:remote / serve:remote требуют @tv/extension-sdk 1.14.0 или новее. У модуля, созданного версией 1.13.0 или более ранней, этих скриптов нет — пересоздайте каркас или добавьте их вручную, как показано в шаге 1.

1. Отдавайте remote со своей машины

@originjs/vite-plugin-federation создаёт remoteEntry.js при сборке, а не в dev-сервере. Поэтому pnpm dev отдаёт приложение вообще без remote, и оболочка, нацеленная на него, получает 404, который браузер показывает как ошибку CORS. Два терминала, две команды:

bash
# терминал 1 — пересборка при каждом изменении
pnpm dev:remote     # vite build --watch

# терминал 2 — отдача собранного
pnpm serve:remote   # vite preview --port 6001 --strictPort

Ваш remote будет здесь:

http://localhost:6001/assets/remoteEntry.js

6001 — закреплённый в каркасе порт preview (порт dev плюс 1000). strictPort задан намеренно: без него vite перескочит на следующий свободный порт и уведёт remote из-под записи реестра, которая на него ссылается.

Если в вашем каркасе нет dev:remote / serve:remote, их эквиваленты — vite build --watch и vite preview --port 6001 --strictPort плюс preview: { port: 6001, strictPort: true, cors: true } в vite.config.ts.

2. Установите модуль в свою песочницу

bash
npx @tv/extension-sdk sandbox install module-manifest.json \
  --sandbox=sbx_... \
  --remote-entry=http://localhost:6001/assets/remoteEntry.js

Два вызова к tv-api вашей собственной песочницы, по порядку:

  1. POST /api/v1/registry/modules/ingest с вашим манифестом и URL remote — это та запись реестра, из которой рисует оболочка.
  2. POST /api/v1/licenses на наполненное здание: оболочка рисует из состояния лицензий, поэтому зарегистрированный, но нелицензированный модуль просто отсутствует. Уже существующая лицензия отвечает 409, и команда считает это успехом — её безопасно запускать повторно.

--sandbox=<id> за один запрос находит URL API, токен, наполненное здание и console URL. Без него используется пара TV_API_URL / TV_API_TOKEN, которую печатает tv-sdk sandbox connect.

Обоим эндпоинтам нужны права администратора платформы — и внутри своей песочницы они у вас есть: tv-api песочницы принимает собственный токен как администратора этого одного API и этой одной базы, и ничего больше (tv-platform#795). Если вам попалась старая заметка в SDK о том, что этот вызов ожидаемо падает с 401/403, она написана до этого изменения.

Смена адреса, с которого вы отдаёте remote, — это повторный запуск команды, а не пересборка оболочки.

3. Откройте

<хост вашей песочницы>/sandbox/<slug вашего модуля>

Хост песочницы — это consoleUrl в записи песочницы (тот же хост, что и apiUrl: оболочка отдаётся на /, API остаётся на /api и /socket.io, поэтому UI и бэкенд у них общий origin). consoleUrl равен null, если для вашей песочницы оболочка не развёрнута.

Оболочка песочницы монтирует один общий маршрут /sandbox/:slug, который ведут поля remoteEntryUrl, federationName и exposeName из вашей записи реестра; маршруты /<slug> продуктивной оболочки тут ни при чём.

4. Войдите

Оболочка песочницы аутентифицируется в реалме Keycloak sandboxes. Самостоятельной регистрации там нет: учётную запись в этом реалме создаёт для вас команда Tango Vision, проставляя в клейм tenant_id значение organizationId вашей песочницы. Напишите на developers@tango.vision и укажите organizationId из записи песочницы.

Чего ожидать, а чего нет

  • Chrome или Firefox, не Safari. Safari блокирует загрузку скрипта с http://localhost на страницу с публичного HTTPS-origin. Chrome при первом запуске может спросить разрешение на доступ к локальной сети — разрешите.
  • Берите токен из контекста платформы, а не из localStorage['access_token']. В оболочке песочницы мост к старому ключу выключен: оболочка, зеркалящая живой access-токен в ключ, читаемый любым скриптом, отдавала бы его чужому JavaScript. Модули, читающие этот ключ напрямую, в оболочке песочницы не аутентифицируются; модули, берущие токен из PlatformContext SDK, работают как обычно. См. PlatformContext.
  • Remote загрузится, только если его пропустят два независимых барьера — CSP браузера и собственный список разрешённых origin у оболочки. В оболочке песочницы оба настроены пропускать localhost. Remote с другого адреса требует изменения обоих, и это запрос к нам, а не настройка на вашей стороне.
  • Лицензионной проверки на этом маршруте нет, но вход всё равно нужен: маршрут находится внутри защищённой области оболочки.
  • Бэкенд вашего модуля всё это не разворачивает. install регистрирует и лицензирует фронтенд-remote. Бэкенд работает там, где вы его запустили, и обращается к tv-api песочницы по сети, как любой другой клиент.

Правила загрузки модуля с localhost

Всё сказанное выше в виде списка. Если страница пустая, одно из этих условий не выполнено.

  1. С localhost загружает только песочная оболочка. Content-Security-Policy рабочей оболочки не допускает http://localhost, а универсальный маршрут модулей в ней выключен. Песочная оболочка допускает loopback-адреса и открывает любой модуль из реестра вашей песочницы по адресу /sandbox/<slug>.
  2. Только loopback. Допускаются http://localhost:<порт> и http://127.0.0.1:<порт>. Адрес в локальной сети, туннель или любой другой хост не допускаются.
  3. Отдавайте сборку, а не dev-сервер. vite dev не создаёт assets/remoteEntry.js: federation-remote существует только в сборке. Запустите pnpm dev:remote и pnpm serve:remote одновременно.
  4. Адрес фиксирован: http://localhost:6001/assets/remoteEntry.js. Preview работает со strictPort, поэтому занятый порт даёт ошибку, а не тихий переход на другой, и с включённым CORS.
  5. Запись в реестре должна указывать на него. tv-sdk sandbox install с параметром --remote-entry=http://localhost:6001/assets/remoteEntry.js регистрирует манифест в вашей песочнице и выдаёт лицензию на созданное здание. Slug в нижнем регистре через дефис, не длиннее 64 символов; remote экспортирует ./Shell.
  6. Chrome или Firefox, не Safari. Оболочка открыта по HTTPS и загружает скрипт с HTTP loopback; Safari это блокирует. Chrome может один раз запросить доступ к устройствам в локальной сети: разрешите.
  7. Модуль загружается только в вашем браузере. localhost это ваш компьютер. Коллега, открыв тот же адрес, получит ошибку загрузки. Чтобы показать модуль другому человеку, разместите собранный бандл на хосте, который допускает песочная оболочка, и попросите нас разрешить этот хост.
  8. Авторизация только через SDK, не через localStorage['access_token']. Песочная оболочка не записывает туда токен. React-контекст не пересекает границу federation, поэтому внутри remote используйте работающие там хуки, например useSelectedBuildingId().
  9. Ваш бэкенд работает на вашем компьютере. Политика оболочки позволяет фронтенду обращаться к http://localhost:<порт>, поэтому локальный бэкенд доступен из браузера. Платформа до него не дотянется: у песочницы нет исходящего доступа в интернет и маршрута к вашему компьютеру, поэтому Copilot не сможет вызвать MCP-эндпоинт на localhost.
  10. i18next и react-i18next в shared либо оба, либо ни одного, и сохраняйте alias use-sync-external-store/shim из шаблона. Нарушение проявляется только внутри оболочки, где ваш CI его не видит.

Если страница пустая

Что вы видитеОбычная причина
404 на remoteEntry.js, показанный как CORSНе запущен pnpm dev:remote, либо запущен pnpm dev — dev-сервер remote не создаёт
Remote грузится с другого портаНет strictPort: vite сменил порт, а запись реестра по-прежнему указывает на 6001
Пустой маршрут, запроса за remote нетМодуль зарегистрирован, но не лицензирован — запустите sandbox install, он делает оба шага
Вход выполнен, но все вызовы API дают 401Модуль читает localStorage['access_token']; перейдите на контекст платформы
Падение из-за второй копии React при монтированииНет алиаса use-sync-external-store/shim; см. Федерация и оболочка

Создано на платформе Tango Vision. Вопросы? developers@tango.vision