Если у вас есть два приложения на React + Vite — хост и микрофронт (remote) — и при общем старте через одну команду всё магически ок, а при раздельном запуске хост падает с 404 на remoteEntry.js, вы не одиноки. Разбираемся, почему так, и показываю рабочие рецепты.
Remote (react-vite/remote) публикует модуль:
// vite.config.js (remote) import federation from '@originjs/vite-plugin-federation' export default defineConfig({ plugins: [ federation({ name: "remote_app", filename: "remoteEntry.js", exposes: { './Button': './src/components/Button' }, shared: ['react','react-dom'] }) ] })
Host (react-vite/host) тянет remote:
// vite.config.js (host) import federation from '@originjs/vite-plugin-federation' export default defineConfig({ plugins: [ federation({ name: 'app', remotes: { remoteApp: 'http://localhost:5001/assets/remoteEntry.js', }, shared: ['react','react-dom'] }) ] })
Импорт в хосте:
// src/App.jsx (host) import Button from 'remoteApp/Button';
Проблема
-
При раздельном запуске: хост запрашивает http://localhost:5001/assets/remoteEntry.js, а remote ещё не готов или отдает другой путь/файл для текущего режима. Результат — 404 и:
-
GET …/remoteEntry.js net::ERR_ABORTED 404
-
Failed to fetch dynamically imported module…
При общем старте командой вида
pnpm --parallel --filter "./**" preview
оба сервиса поднимаются вместе, remote успевает начать отдавать remoteEntry.js, и хост не падает.
Почему это происходит на самом деле
-
Не “синхронный импорт”, а гонка запуска и/или несоответствие режимов.
-
В Vite:
-
В dev-режиме файл remote может быть “виртуальным” и сервиться на лету плагином.
-
В preview-фазе он отдается из dist после vite build.
-
Если хост открылся раньше, remote ещё не слушает порт 5001 или не собран — будет 404.
-
Ещё один частый кейс — запуск в разных режимах (например, host в preview, а remote в dev): тогда пути и поведение могут различаться.
Как воспроизвести и увидеть разницу
# Терминал 1 pnpm --filter "react-vite/remote" preview # или dev # Терминал 2 (сразу или чуть раньше) pnpm --filter "react-vite/host" preview
Если хост открыли раньше, получите 404 на remoteEntry.js.
pnpm --parallel --filter "./**" preview
Обычно remote успевает подняться к первому заходу в хост, и всё ок.
Рабочие рецепты
-
Запускайте в одном режиме на обоих концах.
-
dev+dev или build+preview для обоих. Не мешайте режимы.
-
Гарантируйте порядок (ждите remote).
-
Делайте URL remote динамическим через env
// vite.config.js (host) import { defineConfig, loadEnv } from 'vite' import federation from '@originjs/vite-plugin-federation' export default defineConfig(({ mode }) => { const env = loadEnv(mode, process.cwd(), '') return { plugins: [ federation({ remotes: { remoteApp: env.VITE_REMOTE_URL // например: http://localhost:5001/assets/remoteEntry.js }, shared: ['react','react-dom'] }) ] } })
Теперь можно явно указывать корректный URL для dev/preview через .env:
# .env.development VITE_REMOTE_URL=http://localhost:5001/assets/remoteEntry.js
-
Добавьте простой retry/“обновите страницу”.
-
Иногда банально достаточно дождаться старта remote и перезагрузить хост: Vite подхватит remoteEntry.js.
-
Монорепо-скрипт “одним махом”.
-
Уже работающий подход — общая команда, которая стартует оба сервиса. Это снижает вероятность гонки.
Быстрый чеклист
-
Порты совпадают с конфигом? Host реально указывает на 5001, а remote слушает 5001?
-
Режимы согласованы? dev↔dev, preview↔preview.
-
Remote действительно отдает assets/remoteEntry.js? Откройте URL в браузере.
-
Порядок старта учтен? Ждите remote перед открытием host.
Итоги
-
Симптом: 404 на remoteEntry.js при раздельном запуске.
-
Причина: гонка старта и/или разные режимы сборки/предпросмотра.
-
Решение: стартовать синхронно, ждать готовность remote, унифицировать режимы, вынести URL remote в переменные окружения, при необходимости — добавить ожидание/ретраи.
Следуя этим практикам, вы избавитесь от «мистических» 404 и сделаете запуск предсказуемым как локально, так и в CI/CD.
ссылка на оригинал статьи https://habr.com/ru/articles/938820/
Добавить комментарий