Тунелювати dev-сервер Vite загалом просто — окрім двох речей, на яких ви спіткнетеся першого разу. Сторінка завантажується, а HMR — ні. Або сторінка взагалі не завантажується, бо Vite відхиляє хостнейм тунелю. Обидва випадки розв'язуються одним рядком конфігу, коли знаєш, куди дивитися.
Проблема 1: «Blocked request. This host is not allowed.»
У Vite 5+ за замовчуванням додано захист host-check. Якщо ви відкриваєте URL тунелю й бачите Blocked request. This host is not allowed, це перевірка відхиляє ваш хостнейм *.portpreview.dev.
Виправлення в vite.config.ts:
export default defineConfig({
server: {
host: true, // listen on 0.0.0.0
allowedHosts: ['.portpreview.dev'], // accept any subdomain
},
});
Провідна крапка робить це збігом за суфіксом. Можна вказати там конкретний хостнейм тунелю, якщо хочете суворості, але для щоденної розробки суфікс зручний — URL сесій тунелю змінюються.
Проблема 2: HMR завантажується, потім тихо вмирає
HMR працює по WebSocket. Коли Vite роздає на localhost:5173, а браузер завантажує з https://abc123.portpreview.dev, HMR-клієнт намагається під'єднатися до URL, який йому назвав сервер, — локального. Тунель його не пробрасує, тож WebSocket падає, і HMR тихо зупиняється.
Виправте конфіг HMR:
export default defineConfig({
server: {
host: true,
allowedHosts: ['.portpreview.dev'],
hmr: {
clientPort: 443, // browser connects on 443 (HTTPS)
protocol: 'wss', // secure WebSocket through the tunnel
},
},
});
Тепер HMR-клієнт під'єднується до wss://abc123.portpreview.dev (порт 443), тунель пробрасує upgrade, і правки поширюються як очікувано. Якщо потрібне лише статичне перезавантаження й HMR через тунель не важливий, це можна пропустити — але доведеться багато тиснути cmd-R.
Навіщо взагалі тунелювати Vite
Три реальні причини:
- Мобільне тестування. Відкрийте URL на телефоні, побачите той самий білд із HMR. Краще за шеринг екрана чи емулятори під кожен пристрій. Повний патерн див. у мобільному тестуванні через тунель.
- Ділитися роботою в процесі. Надішліть посилання дизайнеру або PM — вони побачать вашу гілку наживо. Без кроку деплою.
- Флоу OAuth і вебхуків, що потребують HTTPS. Роздавані Vite фронтенди, що спілкуються зі Stripe (лише redirect), Auth0 тощо. Вибір розглянуто у mkcert vs тунель.
SvelteKit, Astro, SolidStart — усі на Vite
Конфіги вище застосовні до будь-якого фреймворку, що роздає Vite як dev-сервер. У SvelteKit vite.config.js тієї ж форми. В Astro власний astro.config.mjs із підоб'єктом vite — помістіть ті самі опції server туди. SolidStart, Nuxt 3 (через Vite) і Qwik City: той самий патерн.
Production-білди — інша історія
Усе вище — конфіг dev-сервера. Коли ви запускаєте vite preview або роздаєте зібраний бандл, ніщо з цього не має значення, бо немає ні HMR, ні мідлвару host-check. На цьому етапі тунель просто пробрасує статичні файли.
Кілька дрібниць
- Суворий host-CORS. Якщо фронтенд звертається до API на іншому origin (інший порт localhost або окремий API-тунель), налаштуйте CORS на боці API. Vite за замовчуванням не проксує, доки ви не вкажете це через
server.proxy. - Застосунки з активним WebSocket. HMR Vite — це один WebSocket. Якщо застосунок використовує інший WebSocket для стану гри, чату чи живих даних, він окремий і теж має бути налаштований у клієнтському коді на URL тунелю.
- URL тунелю в env-файлах. Ми кладемо активний URL тунелю в
.env.localякVITE_PUBLIC_URL, коли фронтенду потрібно знати власну публічну адресу.import.meta.env.VITE_PUBLIC_URLчитає його в клієнті.
Покроково
- Додайте блок
server.host,allowedHostsіhmrдо конфігу Vite. - Перезапустіть dev-сервер.
- Виконайте
npx portpreview 5173(або порт, який використовує Vite). - Відкрийте HTTPS-URL у браузері або на телефоні.
- Відредагуйте компонент. Переконайтеся, що HMR оновлює сторінку без повного перезавантаження.
Якщо HMR не оновлює, відкрийте консоль браузера — Vite логує спробу WebSocket-з'єднання, і ви побачите URL, до якого він звертався. Це покаже, чи спрацювала зміна hmr.clientPort/protocol.
Приєднайтеся до списку очікування PortPreview заради тунелів, що за замовчуванням зберігають WebSocket-upgrade.