Hot Reload — je technologie, při které jsou změny ve zdrojovém kódu aplikovány na běžící aplikaci bez úplného znovunačtení stránky a bez ztráty aktuálního stavu. Na rozdíl od Live Reload, který jednoduše obnoví celou stránku, horké znovunačtení nahrazuje pouze upravené moduly za běhu. Podle Webpack, 2024 zkracuje Hot Module Replacement (HMR) dobu vývojového cyklu až o 80% díky zachování stavu komponent.
Hlavní
Hot Reload — je vývojový mechanismus, při kterém se změny ve zdrojových souborech okamžitě projeví v běžící aplikaci bez jejího restartování. Vývojář upravuje kód v editoru, uloží soubor a výsledek je okamžitě viditelný v prohlížeči nebo emulátoru.
Klíčovou vlastností technologie je zachování stavu aplikace. Proměnné v paměti, data ve formulářích, aktuální navigace — vše zůstává na svém místě. Vývojář nemusí opakovat posloupnost akcí, aby se vrátil k potřebné obrazovce.
Ve vývoji webu je Hot Reload implementován prostřednictvím mechanismu Hot Module Replacement (HMR). Bundler sleduje změny souborů, určuje, které moduly jsou ovlivněny, a posílá aktualizovaný kód do prohlížeče přes WebSocket. Prohlížeč nahrazuje pouze tyto moduly bez znovunačtení stránky.
Popularita Hot Reload vzrostla s rozšířením jednostránkových aplikací (SPA), kde úplné znovunačtení stránky ničí celý stav klientské aplikace. React, Vue, Angular a další frameworky doporučují HMR jako hlavní režim vývoje.
Mechanismus HMR se skládá ze čtyř fází. Bundler na straně serveru zkompiluje upravený modul, vytvoří JSON záplatu s novou verzí kódu a pošle ji do prohlížeče přes WebSocket připojení. Část prohlížeče HMR runtime příjme záplatu, nahradí starý modul novým a informuje odběratele modulu.
Webpack Dev Server používá WebSocket pro komunikaci s klientem. Při změně souboru vytvoří bundler hot-update.js a hot-update.json s manifestem změn. Klient automaticky načte tyto soubory prostřednictvím JSONP.
// webpack.config.js - nastavení 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 v prohlížeči zkontroluje, zda nahrazovaný modul podporuje accept. Pokud modul deklaroval module.hot.accept(), runtime jej nahradí na místě a spustí callback aktualizace. Pokud accept není deklarován, HMR spadne na vyšší úroveň, k nadřazenému modulu.
V React Fast Refresh je tato logika vestavěna na úrovni frameworku — není třeba ručně psát module.hot.accept v každém souboru. Babel-plugin react-refresh/babel přidává kód, který bezpečně nahrazuje komponenty bez ztráty stavu.
Tyto tři termíny jsou často zaměňovány, ale radikálně se liší chováním. Live Reload znovu načte celou stránku při každé změně — veškerý stav je ztracen. Full Reload nastává při úplném restartování vývojového serveru se ztrátou nejen klientského, ale i serverového stavu.
| Typ | Znovunačtení stránky | Zachování stavu | Rychlost |
|---|---|---|---|
| Hot Reload (HMR) | Ne | Ano | Okamžitě |
| Live Reload | Ano | Ne | 1-3 s |
| Full Reload | Ano | Ne | 3-10 s |
Volba mezi Hot a Live přímo ovlivňuje rychlost vývoje. Při HMR trvá cyklus „změnil jsem kód → viděl jsem výsledek“ 50-200 ms. Při Live Reload — 1-3 sekundy plus čas na obnovení kontextu. Během pracovního dne představuje rozdíl desítky minut ušetřeného času.
React Fast Refresh — oficiální implementace Hot Reload optimalizovaná pro React komponenty. Nahradila starý mechanismus React Hot Loader, který byl nestabilní a vyžadoval ruční konfiguraci. Fast Refresh je vestavěn do Create React App, Next.js, Vite a Webpacku prostřednictvím react-refresh/babel.
Fast Refresh správně zachovává stav funkcionálních komponent při změně jejich kódu. Pokud měníte pouze JSX značky — useState a další háky si zachovávají své hodnoty. Pokud se mění logika háku — dojde k přemontování komponenty.
// Příklad - stav zachován při změně 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 nezachovává stav, pokud nový kód obsahuje chybu kompilace. Pokud komponenta není exportována jako výchozí (named export), stav se také nemusí zachovat. Doporučuje se používat default export pro komponenty a obalovat exporty do memo, pokud je třeba zaručit zachování stavu.
Moderní bundlery poskytují HMR. Webpack — průkopník HMR s flexibilní konfigurací přes devServer.hot. Vite používá nativní ESM a esbuild pro okamžitý HMR bez bundlování. Parcel — HMR bez konfigurace. Turbopack — nový bundler od Vercelu s HMR na Rustu.
| Nástroj | Typ HMR | Konfigurace | Ekosystém |
|---|---|---|---|
| Webpack 5 | HMR přes WebSocket | devServer.hot: true | React, Vue, Angular |
| Vite | Native ESM HMR | Z krabice | React, Vue, Svelte |
| Parcel 2 | Zero-config HMR | Není vyžadováno | React, Vue, TS |
| Turbopack | Incremental HMR | Z krabice | Next.js |
Vite vyniká rychlostí — HMR ve Vite funguje přes nativní ES moduly prohlížeče. Při změně souboru Vite pošle pouze tento modul přes import(), bez překompilování celého projektu. Webpack kompiluje každý modul celý, což při velkých projektech HMR zpomaluje.
Podíváme se na konfiguraci HMR pro různé bundlery. Ve Webpacku je třeba nastavit hot: true v devServer a přidat react-refresh/babel. Ve Vite HMR funguje z krabice s libovolným presetem. V Next.js je Fast Refresh ve výchozím nastavení zapnutý přes turbokompilátor.
// 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 nefunguje správně ve všech scénářích. CSS moduly s dynamickými třídami se nemusí aplikovat. Globální proměnné a singly (Redux store, router) se mohou při znovunačtení resetovat. Těžké knihovny při HMR někdy generují úniky paměti kvůli nahrazení modulů bez GC.
Řešením problémů HMR je izolovat horký kód do čistých komponent bez vedlejších účinků. Vedlejší účinky (odběry WebSocket, časovače) by měly být čištěny v useEffect. Pro Redux se doporučuje persister, který ukládá stav do sessionStorage. CSS řešení jako CSS Modules nebo styled-components fungují správně s HMR bez další konfigurace.
Další omezení — ladění v produkci: HMR je úmyslně vypnut v produkčním sestavení. Zdrojový kód je minifikován a horká výměna v produkci je nemožná. Pro ladění chyb v produkci se používají source mapy a logování, ale ne HMR.
Často kladené otázky
Hot Reload nahrazuje pouze upravený modul bez znovunačtení stránky a zachovává stav. Live Reload znovu načte celou stránku — stav je ztracen, aplikace se spouští znovu z počáteční obrazovky.
V projektech na Create React App a Vite je HMR ve výchozím nastavení zapnutý. Ve Webpacku je třeba přidat devServer: { hot: true } a @pmmmwh/react-refresh-webpack-plugin. V Next.js Fast Refresh funguje bez konfigurace.
Důvodem je chyba kompilace v novém kódu, named export místo default, změna signatury háku nebo přímá mutace stavu. React Fast Refresh bezpečně resetuje komponentu pouze tehdy, když je to nutné pro správnou funkci.
Ano, všechny moderní bundlery podporují HMR s TypeScriptem. Vite používá esbuild pro transpilaci TS. Webpack — ts-loader nebo babel s @babel/preset-typescript. Fast Refresh správně funguje s typovanými komponentami.
Zkontrolujte konzoli prohlížeče na chyby WebSocket připojení. Ujistěte se, že devServer.hot: true je zapnutý. Pro Vite zkontrolujte port HMR. Pokud se problém nevyřeší — proveďte úplné znovunačtení stránky (F5) a zkontrolujte konzoli bundleru.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také