Hot Reload — فناوری است که در آن تغییرات در کد منبع بدون بارگیری مجدد کامل صفحه و بدون از دست دادن وضعیت فعلی به برنامه در حال اجرا اعمال میشوند. به عکس Live Reload که کل صفحه را تماماً بهروز میکند، بارگیری مجدد گرم تنها ماژولهای تغییریافته را در حال اجرا جایگزین میکند. به گزارش Webpack, 2024، Hot Module Replacement (HMR) زمان چرخه توسعه را با حفظ وضعیت کامپوننتها تا ٨٠٪ کاهش میدهد.
اصلی
Hot Reload — مکانیزم توسعه است که در آن تغییرات در فایلهای منبع بلافاصله در برنامه در حال اجرا بدون راهاندازی مجدد منعکس میشوند. توسعهدهنده کد را در ویرایشگر ویرایش میکند، فایل را ذخیره میکند و نتیجه بلافاصله در مرورگر یا شبیهساز قابل مشاهده است.
ویژگی کلیدی فناوری حفظ وضعیت برنامه است. متغیرهای در حافظه، دادههای در فرمها، ناوبری فعلی — همه چیز در جای خود باقی میماند. توسعهدهنده نیازی به تکرار تسلسل عملیات برای بازگشت به صفحه مورد نیاز ندارد.
در توسعه وب، Hot Reload از طریق مکانیزم Hot Module Replacement (HMR) پیادهسازی میشود. باندلر تغییرات فایلها را ردیابی میکند، تعیین میکند که کدام ماژولها تحت تأثیر قرار گرفتهاند و کد بهروزشده را از طریق WebSocket به مرورگر ارسال میکند. مرورگر بدون بارگیری مجدد صفحه تنها آن ماژولها را جایگزین میکند.
محبوبیت Hot Reload با گسترش برنامههای تکصفحهای (SPA) افزایش یافت، جایی که بارگیری مجدد کامل صفحه تمام وضعیت برنامه مشتری را از بین میبرد. React، Vue، Angular و سایر فریمورکها HMR را به عنوان حالت اصلی توسعه توصیه میکنند.
مکانیزم HMR از چهار مرحله تشکیل شده است. باندلر در طرف سرور ماژول تغییریافته را کامپایل میکند، یک پاتچ JSON با نسخه جدید کد ایجاد میکند و آن را از طریق اتصال WebSocket به مرورگر ارسال میکند. بخش مرورگر HMR runtime پاتچ را میپذیرد، ماژول قدیمی را با ماژول جدید جایگزین میکند و مشترکان ماژول را مطلع میکند.
Webpack Dev Server برای ارتباط با مشتری از WebSocket استفاده میکند. هنگام تغییر فایل، باندلر hot-update.js و hot-update.json را با مانیفست تغییرات ایجاد میکند. مشتری این فایلها را از طریق JSONP به صورت خودکار بارگیری میکند.
// webpack.config.js - راهاندازی 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 در مرورگر بررسی میکند که آیا ماژول جایگزینشونده accept را پشتیبانی میکند. اگر ماژول module.hot.accept() را اعلام کرده باشد، runtime آن را در همان جا جایگزین میکند و فراخوان بهروزرسانی را اجرا میکند. اگر accept اعلام نشده باشد، HMR به سطح بالاتر، به ماژول والد بازگشت میخورد.
در React Fast Refresh این منطق در سطح فریمورک ساخته شده است — نیازی به نوشتن دستی module.hot.accept در هر فایل نیست. Babel-plugin react-refresh/babel کدی را اضافه میکند که بدون از دست دادن وضعیت، کامپوننتها را به طور ایمن جایگزین میکند.
این سه اصطلاح اغلب اشتباه گرفته میشوند، اما از لحاظ رفتار اساساً متفاوت هستند. Live Reload در هر تغییری کل صفحه را تماماً بارگیری مجدد میکند — تمام وضعیت از دست میرود. Full Reload با راهاندازی مجدد کامل سرور توسعه با از دست دادن نه تنها وضعیت مشتری، بلکه وضعیت سرور نیز انجام میشود.
| نوع | بارگیری مجدد صفحه | حفظ وضعیت | سرعت |
|---|---|---|---|
| Hot Reload (HMR) | خیر | بله | فوری |
| Live Reload | بله | خیر | 1-3 ثانیه |
| Full Reload | بله | خیر | 3-10 ثانیه |
انتخاب بین Hot و Live مستقیماً بر سرعت توسعه تأثیر میگذارد. در HMR چرخه «کد را تغییر دادم → نتیجه را دیدم» ۵۰-۲۰۰ میلیثانیه طول میکشد. در Live Reload — ۱-۳ ثانیه به علاوه زمان بازیابی زمینه. در طول روز کاری، تفاوت دههها دقیقه صرفهجویی زمان است.
React Fast Refresh — پیادهسازی رسمی Hot Reload است که برای کامپوننتهای React بهینهسازی شده است. آن جایگزین مکانیزم قدیمی React Hot Loader شد که ناپایدار بود و نیازمند پیکربندی دستی بود. Fast Refresh از طریق react-refresh/babel به Create React App، Next.js، Vite و Webpack ورود شده است.
Fast Refresh وضعیت کامپوننتهای تابعی را هنگام تغییر کد آنها به درستی حفظ میکند. اگر تنها نشانهگذاری JSX را تغییر میدهید — useState و سایر هوکها مقادیر خود را حفظ میکنند. اگر منطق هوک تغییر کند — مونتاژ مجدد کامپوننت انجام میشود.
// مثال - وضعیت هنگام تغییر 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 وضعیت را حفظ نمیکند. اگر کامپوننت به صورت پیشفرض (default) صادر نشود و به جای آن با نام صادر شود (named export)، وضعیت نیز ممکن است حفظ نشود. توصیه میشود از default export برای کامپوننتها استفاده کنید و در صورت نیاز به تضمین حفظ وضعیت، ایکسپورتها را در memo بپیچید.
باندلرهای مدرن HMR را ارائه میدهند. Webpack — پیشگام HMR با پیکربندی انعطافپذیر از طریق devServer.hot. Vite از ESM و esbuild جهت HMR فوری بدون باندل استفاده میکند. Parcel — HMR بدون پیکربندی. Turbopack — باندلر جدید از Vercel با HMR در Rust.
| ابزار | نوع HMR | پیکربندی | اکوسیستم |
|---|---|---|---|
| Webpack 5 | HMR از طریق WebSocket | devServer.hot: true | React, Vue, Angular |
| Vite | Native ESM HMR | خودکار | React, Vue, Svelte |
| Parcel 2 | Zero-config HMR | نیازی نیست | React, Vue, TS |
| Turbopack | Incremental HMR | خودکار | Next.js |
Vite از لحاظ سرعت متمایز است — HMR در Vite از طریق ماژولهای ES طبیعی مرورگر کار میکند. هنگام تغییر فایل، Vite بدون کامپایل مجدد کل پروژه تنها آن ماژول را از طریق import() ارسال میکند. Webpack هر ماژول را کاملاً کامپایل میکند که در پروژههای بزرگ HMR را کند میکند.
تنظیمات HMR را برای باندلرهای مختلف بررسی میکنیم. در Webpack باید hot: true را در devServer تنظیم کرده و react-refresh/babel را اضافه کنید. در Vite HMR با هر پرستی خودکار کار میکند. در Next.js Fast Refresh از طریق توربوکامپایلر به صورت پیشفرض فعال است.
// 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 در همه سناریوها به درستی کار نمیکند. ماژولهای CSS با کلاسهای پویا ممکن است اعمال نشوند. متغیرهای سراسری و اشیای تکتا (Redux store، روتر) ممکن است در بارگیری مجدد تنظیم شوند. کتابخانههای سنگین در HMR گاهی به دلیل جایگزینی ماژولها بدون GC نشت حافظه ایجاد میکنند.
راه حل مشکلات HMR — جداسازی کد گرم در کامپوننتهای خالص بدون عوارض جانبی است. عوارض جانبی (اشتراک WebSocket، تایمرها) باید در useEffect پاکسازی شوند. برای Redux پرسیستری توصیه میشود که وضعیت را در sessionStorage ذخیره کند. راهحلهای CSS مانند CSS Modules یا styled-components بدون تنظیمات اضافی با HMR به درستی کار میکنند.
یک محدودیت دیگر — تصحیح اشکالزدایی در تولید: HMR به عمد در نسخه تولید غیرفعال میشود. کد منبع مینیفیکیشده میشود و جایگزینی گرم در تولید امکانپذیر نیست. برای تصحیح خطاهای تولید از source maps و گزارشنویسی استفاده میشود، نه HMR.
سوالات متداول
Hot Reload بدون بارگیری مجدد صفحه تنها ماژول تغییریافته را جایگزین میکند و وضعیت را حفظ میکند. Live Reload کل صفحه را تماماً بارگیری مجدد میکند — وضعیت از دست میرود، برنامه از صفحه ابتدایی مجدداً شروع میشود.
در پروژههای Create React App و Vite HMR به صورت پیشفرض فعال است. در Webpack باید devServer: { hot: true } و @pmmmwh/react-refresh-webpack-plugin را اضافه کنید. در Next.js Fast Refresh بدون تنظیمات کار میکند.
دلیل — خطای کامپایل در کد جدید، named export به جای default، تغییر امضای هوک یا تغییر مستقیم وضعیت. React Fast Refresh کامپوننت را تنها در صورت نیاز برای کارکرد صحیح به طور ایمن تنظیم میکند.
بله، همه باندلرهای مدرن HMR را با TypeScript پشتیبانی میکنند. Vite از esbuild برای ترانسپایل TS استفاده میکند. Webpack — ts-loader یا babel با @babel/preset-typescript. Fast Refresh با کامپوننتهای تایپشده به درستی کار میکند.
کنسول مرورگر را برای خطاهای اتصال WebSocket بررسی کنید. مطمئن شوید که devServer.hot: true فعال است. برای Vite پورت HMR را بررسی کنید. اگر مشکل برطرف نشد — کل صفحه را مجدداً بارگیری کنید (F5) و کنسول باندلر را بررسی کنید.
نتیجه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید