Hot Reload là công nghệ áp dụng các thay đổi trong mã nguồn vào ứng dụng đang chạy mà không cần tải lại toàn bộ trang và không làm mất trạng thái hiện tại. Không giống như Live Reload, chỉ đơn giản làm mới toàn bộ trang, tải lại nóng chỉ thay thế các module đã được sửa đổi ngay lập tức. Theo Webpack, 2024, Hot Module Replacement (HMR) giảm thời gian chu kỳ phát triển lên đến 80% nhờ giữ nguyên trạng thái của các component.
Những điểm chính
Hot Reload là cơ chế phát triển trong đó các thay đổi trong tệp nguồn được phản ánh ngay lập tức trong ứng dụng đang chạy mà không cần khởi động lại. Nhà phát triển chỉnh sửa mã trong trình soạn thảo, lưu tệp và kết quả hiển thị ngay lập tức trong trình duyệt hoặc trình giả lập.
Tính năng chính của công nghệ này là giữ nguyên trạng thái ứng dụng. Các biến trong bộ nhớ, dữ liệu trong biểu mẫu, điều hướng hiện tại — mọi thứ vẫn giữ nguyên. Nhà phát triển không cần lặp lại một chuỗi hành động để quay lại màn hình cần thiết.
Trong phát triển web, Hot Reload được triển khai thông qua cơ chế Hot Module Replacement (HMR). Bundler theo dõi các thay đổi của tệp, xác định module nào bị ảnh hưởng và gửi mã đã cập nhật đến trình duyệt qua WebSocket. Trình duyệt chỉ thay thế các module đó mà không tải lại trang.
Sự phổ biến của Hot Reload tăng vọt cùng với sự phát triển của ứng dụng trang đơn (SPA), nơi tải lại toàn bộ trang phá hủy toàn bộ trạng thái ứng dụng client. React, Vue, Angular và các framework khác khuyến nghị HMR làm chế độ phát triển chính.
Cơ chế HMR bao gồm bốn giai đoạn. Bundler ở phía máy chủ biên dịch module đã thay đổi, tạo bản vá JSON với phiên bản mã mới và gửi nó đến trình duyệt qua kết nối WebSocket. Thời gian chạy HMR phía trình duyệt nhận bản vá, thay thế module cũ bằng module mới và thông báo cho người đăng ký của module.
Webpack Dev Server sử dụng WebSocket để giao tiếp với client. Khi một tệp thay đổi, bundler tạo hot-update.js và hot-update.json với bảng kê các thay đổi. Client tự động tải các tệp này qua JSONP.
// webpack.config.js - thiết lập HMR
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
devServer: {
hot: true,
liveReload: false
},
plugins: [new HtmlWebpackPlugin()]
};
Thời gian chạy HMR trong trình duyệt kiểm tra xem module đang được thay thế có hỗ trợ accept hay không. Nếu module đã khai báo module.hot.accept(), thời gian chạy sẽ thay thế nó ngay tại chỗ và chạy callback cập nhật. Nếu accept không được khai báo, HMR sẽ fallback lên cấp module cha.
Trong React Fast Refresh, logic này được tích hợp ở cấp framework — không cần viết thủ công module.hot.accept trong mỗi tệp. Plugin Babel react-refresh/babel thêm mã thay thế component an toàn mà không làm mất trạng thái.
Ba thuật ngữ này thường bị nhầm lẫn, nhưng chúng khác nhau hoàn toàn về hành vi. Live Reload tải lại toàn bộ trang khi có bất kỳ thay đổi nào — tất cả trạng thái đều mất. Full Reload xảy ra khi máy chủ phát triển được khởi động lại hoàn toàn, làm mất không chỉ trạng thái client mà còn cả trạng thái máy chủ.
| Loại | Tải lại trang | Giữ trạng thái | Tốc độ |
|---|---|---|---|
| Hot Reload (HMR) | Không | Có | Tức thì |
| Live Reload | Có | Không | 1-3 giây |
| Full Reload | Có | Không | 3-10 giây |
Việc chọn giữa Hot và Live ảnh hưởng trực tiếp đến tốc độ phát triển. Với HMR, chu kỳ “chỉnh sửa mã → xem kết quả” mất 50-200 ms. Với Live Reload — 1-3 giây cộng với thời gian khôi phục ngữ cảnh. Trong một ngày làm việc, sự khác biệt lên đến hàng chục phút tiết kiệm được.
React Fast Refresh là triển khai Hot Reload chính thức được tối ưu hóa cho component React. Nó đã thay thế cơ chế React Hot Loader cũ, vốn không ổn định và yêu cầu cấu hình thủ công. Fast Refresh được tích hợp trong Create React App, Next.js, Vite và Webpack thông qua react-refresh/babel.
Fast Refresh giữ nguyên trạng thái của functional component khi mã của chúng thay đổi. Nếu bạn chỉ thay đổi đánh dấu JSX, useState và các hook khác giữ nguyên giá trị của chúng. Nếu logic của hook thay đổi, component sẽ được gắn kết lại.
// Ví dụ - trạng thái được giữ khi JSX thay đổi
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 không giữ trạng thái nếu mã mới chứa lỗi biên dịch. Nếu component không được xuất theo mặc định (named export), trạng thái cũng có thể không được giữ lại. Nên sử dụng export default cho component và bọc export trong memo nếu cần đảm bảo giữ trạng thái.
Các bundler hiện đại cung cấp HMR. Webpack là người tiên phong về HMR với cấu hình linh hoạt qua devServer.hot. Vite sử dụng ESM gốc và esbuild để HMR tức thì mà không cần bundling. Parcel cung cấp HMR không cần cấu hình. Turbopack là bundler mới từ Vercel với HMR dựa trên Rust.
| Công cụ | Loại HMR | Cấu hình | Hệ sinh thái |
|---|---|---|---|
| Webpack 5 | HMR qua WebSocket | devServer.hot: true | React, Vue, Angular |
| Vite | HMR ESM gốc | Tích hợp sẵn | React, Vue, Svelte |
| Parcel 2 | HMR không cấu hình | Không cần | React, Vue, TS |
| Turbopack | HMR tăng dần | Tích hợp sẵn | Next.js |
Vite nổi bật về tốc độ — HMR trong Vite hoạt động thông qua module ES gốc của trình duyệt. Khi một tệp thay đổi, Vite chỉ gửi module đó qua import(), mà không biên dịch lại toàn bộ dự án. Webpack biên dịch từng module hoàn toàn, làm chậm HMR trong các dự án lớn.
Hãy xem thiết lập HMR cho các bundler khác nhau. Trong Webpack, cần đặt hot: true trong devServer và thêm react-refresh/babel. Trong Vite, HMR hoạt động tích hợp với bất kỳ cài đặt trước nào. Trong Next.js, Fast Refresh được bật theo mặc định thông qua trình biên dịch turbo.
// 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 không hoạt động chính xác trong mọi tình huống. CSS module với lớp động có thể không được áp dụng. Biến toàn cục và singleton (store Redux, router) có thể bị đặt lại khi tải lại. Thư viện nặng với HMR đôi khi có thể gây rò rỉ bộ nhớ do thay thế module mà không có GC.
Giải pháp cho các vấn đề HMR là cô lập mã nóng vào các component thuần túy không có tác dụng phụ. Các tác dụng phụ (đăng ký WebSocket, bộ đếm thời gian) nên được dọn dẹp trong useEffect. Đối với Redux, nên sử dụng persister lưu trạng thái trong sessionStorage. Các giải pháp CSS như CSS Modules hoặc styled-components hoạt động chính xác với HMR mà không cần cấu hình thêm.
Một hạn chế khác là gỡ lỗi trong môi trường production: HMR bị vô hiệu hóa có chủ đích trong bản build production. Mã nguồn được thu nhỏ và việc thay thế nóng trong production là không thể. Để gỡ lỗi lỗi trong production, hãy sử dụng source map và ghi nhật ký, nhưng không phải HMR.
Câu hỏi thường gặp
Hot Reload chỉ thay thế module đã thay đổi mà không tải lại trang và giữ nguyên trạng thái. Live Reload tải lại toàn bộ trang — trạng thái mất, ứng dụng khởi động lại từ màn hình ban đầu.
Trong các dự án sử dụng Create React App và Vite, HMR được bật theo mặc định. Trong Webpack, cần thêm devServer: { hot: true } và @pmmmwh/react-refresh-webpack-plugin. Trong Next.js, Fast Refresh hoạt động mà không cần cấu hình.
Nguyên nhân là lỗi biên dịch trong mã mới, named export thay vì default, thay đổi chữ ký hook hoặc thay đổi trực tiếp state. React Fast Refresh đặt lại component một cách an toàn chỉ khi cần thiết cho hoạt động chính xác.
Có, tất cả các bundler hiện đại đều hỗ trợ HMR với TypeScript. Vite sử dụng esbuild để biên dịch TS. Webpack sử dụng ts-loader hoặc babel với @babel/preset-typescript. Fast Refresh hoạt động chính xác với component có kiểu.
Kiểm tra bảng điều khiển trình duyệt để tìm lỗi kết nối WebSocket. Đảm bảo devServer.hot: true được bật. Đối với Vite, kiểm tra cổng HMR. Nếu vấn đề vẫn còn, thực hiện tải lại toàn bộ trang (F5) và kiểm tra bảng điều khiển của bundler.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm