← Назад к вопросам
За счет чего при разработке всегда показана свежая версия кода?
1.0 Junior🔥 141 комментариев
#Soft Skills и рабочие процессы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Механизм отображения свежей версии кода при разработке
Hot Module Replacement (HMR) и автоматический перезагрузка - вот два основных механизма, которые позволяют видеть актуальный код при разработке. Это обеспечивается инструментами сборки и девелопмент-сервером.
1. Hot Module Replacement (HMR)
Это основной механизм, используемый в современных фреймворках:
// Next.js / Webpack / Vite используют HMR
// Когда вы меняете код:
// 1. Devtools замечает изменение файла
// 2. Пересобирает только изменённый модуль
// 3. Отправляет обновление в браузер через WebSocket
// 4. JavaScript заменяет старый модуль на новый
// 5. Состояние компонента сохраняется
Пример с React:
// Компонент с HMR
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
// Измени текст -> автоматически обновится
// Состояние (count) сохранится!
2. File Watching (Наблюдение за файлами)
Devserver отслеживает изменения файлов в реальном времени:
// Webpack / Vite / Next.js используют chokidar или встроенные системы
const chokidar = require('chokidar');
const watcher = chokidar.watch('src/**/*.js');
watcher.on('change', (path) => {
console.log(`File changed: ${path}`);
// Запустить пересборку
rebuildAndNotifyBrowser();
});
3. WebSocket соединение (Dev Server <-> Browser)
// В браузере
const ws = new WebSocket('ws://localhost:3000/hot-update');
ws.onmessage = (event) => {
const { type, path } = JSON.parse(event.data);
if (type === 'update') {
console.log(`Hot update for: ${path}`);
// Загрузить новый модуль
reloadModule(path);
} else if (type === 'full-reload') {
// Если HMR невозможен - полная перезагрузка
location.reload();
}
};
4. Полная перезагрузка страницы (Fallback)
Когда HMR не подходит (например, изменение конфига):
// Иногда браузер полностью перезагружает страницу
// Это происходит когда:
// 1. Изменился webpack/vite конфиг
// 2. Изменился CSS (зависит от настроек)
// 3. Обновился Node модуль
location.reload();
Примеры в популярных инструментах
Next.js с Fast Refresh:
// pages/index.tsx
import { useState } from 'react';
export default function Home() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
{/* Измени текст здесь -> HMR обновит, count останется прежним */}
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}
При npm run dev:
- Next.js запускает dev server на localhost:3000
- Вы меняете код
- Fast Refresh пересобирает файл (milliseconds)
- Отправляет обновление через WebSocket
- React заменяет только изменённый компонент
- Состояние сохраняется
Vite с HMR:
// vite.config.js
export default {
server: {
middlewareMode: false,
hmr: {
host: 'localhost',
port: 5173,
protocol: 'ws'
}
}
};
Как браузер знает о изменениях
// 1. Dev Server отправляет сообщение через WebSocket
const message = {
type: 'update',
event: 'vite:beforeUpdate',
updates: [
{
type: 'js-update',
event: 'vite:beforeUpdate',
path: '/src/components/Counter.tsx',
acceptedPath: '/src/components/Counter.tsx',
timestamp: 1712138123456
}
]
};
// 2. Браузер получает это и выполняет:
if (import.meta.hot) {
import.meta.hot.accept('/src/components/Counter.tsx', () => {
// Переимпортировать обновлённый модуль
import('/src/components/Counter.tsx').then(() => {
console.log('Module updated');
});
});
}
Кэширование и Cache Busting
// Dev server использует query-string для bypass кэша
// Вместо:
// <script src="bundle.js"></script>
// Используется:
// <script src="bundle.js?t=1712138123456"></script>
// Timestamp меняется при каждом обновлении
// Браузер видит новый URL и загружает свежий файл
Процесс обновления в Next.js
1. Разработчик сохраняет файл (Ctrl+S)
↓
2. Webpack/Turbopack замечит изменение
↓
3. Пересобирает только изменённый модуль (~10-100ms)
↓
4. Отправляет сообщение через WebSocket
↓
5. React Fast Refresh получает обновление
↓
6. Заменяет компонент в памяти
↓
7. Компонент перерендеривается
↓
8. Результат виден в браузере (instant!)
Важные моменты
1. HMR работает только в dev mode
// production сборка НЕ имеет HMR
// Всё кэшируется нормально
npm run build // Production сборка
npm run dev // Development с HMR
2. Некоторые изменения требуют полной перезагрузки
// Работает HMR:
// - Изменение логики компонента
// - Изменение стилей (CSS/Tailwind)
// - Изменение JSX
// Требует полной перезагрузки:
// - Изменение окружения (env variables)
// - Изменение конфига вебпака/вайта
// - Удаление/добавление новых файлов
3. Error Overlay
// Если есть ошибка после сохранения:
// Dev server показывает Error Overlay прямо в браузере
// Это позволяет видеть ошибки без открытия Console
// После исправления ошибки -> HMR обновляет
Инструменты и их реализация HMR
| Инструмент | HMR реализация | Скорость |
|---|---|---|
| Webpack 5 | встроенный HMR API | ~500ms-1s |
| Vite | встроенный, быстро | ~50-200ms |
| Turbopack | встроенный, очень быстро | ~10-50ms |
| Parcel | встроенный | ~200-500ms |
| Create React App | React Fast Refresh | ~500ms-1s |
| Next.js | React Fast Refresh + Turbo | ~50-200ms |
Практический пример с console.log
// src/utils/math.js
export function add(a, b) {
console.log('Adding', a, b);
return a + b;
}
// src/App.jsx
import { add } from './utils/math';
export default function App() {
const result = add(2, 3);
return <div>Result: {result}</div>; // Результат: 5
}
// Теперь изменим math.js:
export function add(a, b) {
console.log('Updated adding', a, b); // Изменили текст
return a + b;
}
// При сохранении файла:
// 1. Dev server пересобирает math.js
// 2. Отправляет обновление через WebSocket
// 3. Браузер переимпортирует math.js
// 4. App.jsx автоматически перерендеривается
// 5. Console будет показывать "Updated adding 2 3"
// Всё это происходит мгновенно!