Hot Reload — to technologia, w której zmiany w kodzie źródłowym są stosowane do działającej aplikacji bez pełnego przeładowania strony i bez utraty bieżącego stanu. W przeciwieństwie do Live Reload, który po prostu odświeża całą stronę, gorące przeładowanie zastępuje tylko zmodyfikowane moduły w locie. Według Webpack, 2024, Hot Module Replacement (HMR) skraca czas cyklu programowania do 80% dzięki zachowaniu stanu komponentów.
Najważniejsze
Hot Reload — to mechanizm programowania, w którym zmiany w plikach źródłowych są natychmiast odzwierciedlane w działającej aplikacji bez jej ponownego uruchamiania. Programista edytuje kod w edytorze, zapisuje plik, a wynik jest natychmiast widoczny w przeglądarce lub emulatorze.
Kluczową właściwością technologii jest zachowanie stanu aplikacji. Zmienne w pamięci, dane w formularzach, bieżąca nawigacja — wszystko pozostaje na swoim miejscu. Programista nie musi powtarzać sekwencji działań, aby wrócić do potrzebnego ekranu.
W programowaniu internetowym Hot Reload jest realizowany poprzez mechanizm Hot Module Replacement (HMR). Bundler śledzi zmiany plików, określa, które moduły są dotknięte, i wysyła zaktualizowany kod do przeglądarki przez WebSocket. Przeglądarka zastępuje tylko te moduły bez przeładowania strony.
Popularność Hot Reload wzrosła wraz z rozpowszechnieniem aplikacji jednostronicowych (SPA), gdzie pełne przeładowanie strony niszczy cały stan aplikacji klienckiej. React, Vue, Angular i inne frameworki zalecają HMR jako podstawowy tryb programowania.
Mechanizm HMR składa się z czterech etapów. Bundler po stronie serwera kompiluje zmodyfikowany moduł, tworzy JSON-łatkę z nową wersją kodu i wysyła ją do przeglądarki przez połączenie WebSocket. Część przeglądarkowa HMR runtime przyjmuje łatkę, zastępuje stary moduł nowym i powiadamia subskrybentów modułu.
Webpack Dev Server używa WebSocket do komunikacji z klientem. Przy zmianie pliku bundler tworzy hot-update.js i hot-update.json z manifestem zmian. Klient automatycznie ładuje te pliki przez JSONP.
// webpack.config.js - konfiguracja HMR
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
devServer: {
hot: true,
liveReload: false
},
plugins: [new HtmlWebpackPlugin()]
};
HMR runtime w przeglądarce sprawdza, czy zastępowany moduł obsługuje accept. Jeśli moduł zadeklarował module.hot.accept(), runtime zastępuje go in-place i uruchamia callback aktualizacji. Jeśli accept nie jest zadeklarowany, HMR spada do poziomu wyższego, do modułu nadrzędnego.
W React Fast Refresh ta logika jest wbudowana na poziomie frameworka — nie trzeba ręcznie pisać module.hot.accept w każdym pliku. Babel-plugin react-refresh/babel dodaje kod, który bezpiecznie zastępuje komponenty bez utraty stanu.
Te trzy terminy są często mylone, ale radykalnie różnią się zachowaniem. Live Reload przeładowuje całą stronę przy każdej zmianie — cały stan jest tracony. Full Reload następuje przy pełnym ponownym uruchomieniu serwera programistycznego z utratą nie tylko stanu klienckiego, ale i serwerowego.
| Typ | Przeładowanie strony | Zachowanie stanu | Prędkość |
|---|---|---|---|
| Hot Reload (HMR) | Nie | Tak | Natychmiast |
| Live Reload | Tak | Nie | 1-3 sek |
| Full Reload | Tak | Nie | 3-10 sek |
Wybór między Hot a Live bezpośrednio wpływa na szybkość programowania. Przy HMR cykl „zmieniłem kod → zobaczyłem wynik” zajmuje 50-200 ms. Przy Live Reload — 1-3 sekundy plus czas na przywrócenie kontekstu. W ciągu dnia roboczego różnica wynosi dziesiątki minut zaoszczędzonego czasu.
React Fast Refresh — oficjalna implementacja Hot Reload zoptymalizowana dla komponentów React. Zastąpiła stary mechanizm React Hot Loader, który był niestabilny i wymagał ręcznej konfiguracji. Fast Refresh jest wbudowany w Create React App, Next.js, Vite i Webpack przez react-refresh/babel.
Fast Refresh poprawnie zachowuje stan komponentów funkcyjnych przy zmianie ich kodu. Jeśli zmieniasz tylko znaczniki JSX — useState i inne hooki zachowują swoje wartości. Jeśli zmienia się logika hooka — następuje ponowne zamontowanie komponentu.
// Przykład - stan zachowany przy zmianach JSX
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
);
}
Fast Refresh nie zachowuje stanu, jeśli nowy kod zawiera błąd kompilacji. Jeśli komponent nie jest eksportowany domyślnie (named export), stan również może nie zostać zachowany. Zaleca się używanie default export dla komponentów i owijanie eksportów w memo, jeśli trzeba zagwarantować zachowanie stanu.
Nowoczesne bundlery zapewniają HMR. Webpack — pionier HMR z elastyczną konfiguracją przez devServer.hot. Vite używa natywnego ESM i esbuild do błyskawicznego HMR bez bundlingu. Parcel — zero-config HMR. Turbopack — nowy bundler od Vercel z HMR na Rust.
| Narzędzie | Typ HMR | Konfiguracja | Ekosystem |
|---|---|---|---|
| Webpack 5 | HMR przez WebSocket | devServer.hot: true | React, Vue, Angular |
| Vite | Native ESM HMR | Od razu | React, Vue, Svelte |
| Parcel 2 | Zero-config HMR | Nie wymagane | React, Vue, TS |
| Turbopack | Incremental HMR | Od razu | Next.js |
Vite wyróżnia się szybkością — HMR w Vite działa przez natywne ES-moduły przeglądarki. Przy zmianie pliku Vite wysyła tylko ten moduł przez import(), bez rekompilacji całego projektu. Webpack kompiluje każdy moduł w całości, co przy dużych projektach spowalnia HMR.
Rozważmy konfigurację HMR dla różnych bundlerów. W Webpack należy ustawić hot: true w devServer i dodać react-refresh/babel. W Vite HMR działa od razu z dowolnym presetem. W Next.js Fast Refresh jest włączony domyślnie przez turbokompilator.
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
hmr: {
port: 3001
}
}
});
// webpack.config.js
const ReactRefreshWebpackPlugin =
require('@pmmmwh/react-refresh-webpack-plugin');
module.exports = {
mode: 'development',
devServer: { hot: true },
plugins: [new ReactRefreshWebpackPlugin()],
module: {
rules: [
{
test: /\.jsx?$/u,
use: 'babel-loader'
}
]
}
};
HMR nie działa poprawnie we wszystkich scenariuszach. Moduły CSS z dynamicznymi klasami mogą nie zostać zastosowane. Zmienne globalne i singletonowe (Redux store, router) mogą się zresetować przy przeładowaniu. Ciężkie biblioteki przy HMR czasami generują wycieki pamięci z powodu wymiany modułów bez GC.
Rozwiązanie problemów HMR — wyizolować gorący kod w czyste komponenty bez efektów ubocznych. Efekty uboczne (subskrypcje WebSocket, timery) powinny być czyszczone w useEffect. Dla Redux zaleca się persister, zapisujący stan w sessionStorage. Rozwiązania CSS, takie jak CSS Modules czy styled-components, działają poprawnie z HMR bez dodatkowej konfiguracji.
Kolejne ograniczenie — debugowanie w produkcji: HMR jest celowo wyłączany w kompilacji produkcyjnej. Kod źródłowy jest minifikowany, a gorąca zamiana na produkcji jest niemożliwa. Do debugowania błędów na produkcji używa się source maps i logowania, ale nie HMR.
Często zadawane pytania
Hot Reload zastępuje tylko zmodyfikowany moduł bez przeładowania strony i zachowuje stan. Live Reload przeładowuje całą stronę — stan jest tracony, aplikacja uruchamia się od nowa od ekranu początkowego.
W projektach na Create React App i Vite HMR jest włączony domyślnie. W Webpack należy dodać devServer: { hot: true } i @pmmmwh/react-refresh-webpack-plugin. W Next.js Fast Refresh działa bez konfiguracji.
Przyczyną jest błąd kompilacji w nowym kodzie, named export zamiast default, zmiana sygnatury hooka lub bezpośrednia mutacja stanu. React Fast Refresh bezpiecznie resetuje komponent tylko wtedy, gdy jest to konieczne do poprawnego działania.
Tak, wszystkie nowoczesne bundlery obsługują HMR z TypeScript. Vite używa esbuild do transpilacji TS. Webpack — ts-loader lub babel z @babel/preset-typescript. Fast Refresh działa poprawnie z typowanymi komponentami.
Sprawdź konsolę przeglądarki pod kątem błędów połączenia WebSocket. Upewnij się, że devServer.hot: true jest włączone. Dla Vite sprawdź port HMR. Jeśli problem nie ustępuje — wykonaj pełne przeładowanie strony (F5) i sprawdź konsolę bundlera.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również