Hot Module Replacementê° HotModuleReplacementPluginì íµí´ íì±íë ê²½ì°, í´ë¹ ì¸í°íì´ì¤ë import.meta.webpackHotíë¡í¼í° ë¿ë§ ìëë¼ module.hotíë¡í¼í° ìë ë
¸ì¶ë©ëë¤. strict ESMììë import.meta.webpackHotë§ ì¬ì©í ì ììµëë¤.
ì¼ë°ì ì¼ë¡, ì¬ì©ìë ì¸í°íì´ì¤ì ì ê·¼í ì ìëì§ íì¸í í, ìì
ì ììí©ëë¤. ì를 ë¤ì´, ì
ë°ì´í¸ë 모ëì accept íë ë°©ë²ì ë¤ìê³¼ ê°ìµëë¤.
if (module.hot) {
module.hot.accept('./library.js', function () {
// ì
ë°ì´í¸ë ë¼ì´ë¸ë¬ë¦¬ 모ëë¡ ìì
ì ìííì¸ì...
});
}
// or
if (import.meta.webpackHot) {
import.meta.webpackHot.accept('./library.js', function () {
// ì
ë°ì´í¸ë ë¼ì´ë¸ë¬ë¦¬ 모ëë¡ ìì
ì ìííì¸ìâ¦
});
}ì§ìëë ë©ìëë ë¤ìê³¼ ê°ìµëë¤...
주ì´ì§ dependenciesì ëí ì
ë°ì´í¸ë¥¼ ìë½íê³ í´ë¹ ì
ë°ì´í¸ì ë°ìí기 ìí´ callbackì ì¤íí©ëë¤. ëí, ì íì ìë¬ í¸ë¤ë¬ë¥¼ ì°ê²°í ì ììµëë¤.
module.hot.accept(
dependencies, // 문ìì´ ëë 문ìì´ ë°°ì´
callback, // ìì¡´ì±ì´ ì
ë°ì´í¸ë ë ì¤íí í¨ì
errorHandler // (err, {moduleId, dependencyId}) => {}
);
// ëë
import.meta.webpackHot.accept(
dependencies, // 문ìì´ ëë 문ìì´ ë°°ì´
callback, // ìì¡´ì±ì´ ì
ë°ì´í¸ë ë ì¤íí í¨ì
errorHandler // (err, {moduleId, dependencyId}) => {}
);ESM import를 ì¬ì©íë©´ dependenciesìì ê°ì ¸ì¨ 모ë ì¬ë³¼ì´ ìëì¼ë¡ ì
ë°ì´í¸ë©ëë¤. ì°¸ê³ : ìì¡´ì± ë¬¸ìì´ì importì from 문ìì´ê³¼ ì íí ì¼ì¹í´ì¼ í©ëë¤. ê²½ì°ì ë°ë¼ callbackì ìëµí ì ììµëë¤. callbackìì require()를 ì¬ì©íë ê²ì ì¬ê¸°ìì ìë¯¸ê° ììµëë¤.
CommonJS를 ì¬ì©í ë callbackìì require()를 ì¬ì©í´ì ìì¡´ì±ì ìëì¼ë¡ ì
ë°ì´í¸í´ì¼ í©ëë¤. callbackì ìëµíë ê²½ì°ë ììµëë¤.
(err, {moduleId, dependencyId}) => {}
err: ESM ìì¡´ì±ì ì¬ì©í ë ë ë²ì§¸ ì¸ì ëë ìì¡´ì± ì¤í ì¤ì ì½ë°±ì ìí´ ë°ìí ìë¬.moduleId: íì¬ ëª¨ë id.dependencyId: (첫 ë²ì§¸) ë³ê²½ë ìì¡´ì±ì 모ë id.ìì²´ì ì¼ë¡ ì ë°ì´í¸ë¥¼ ìë½í©ëë¤.
module.hot.accept(
errorHandler // ì ë²ì ì íê°í ë ìë¬ë¥¼ ì²ë¦¬íë í¨ì
);
// ëë
import.meta.webpackHot.accept(
errorHandler // ì ë²ì ì íê°í ë ìë¬ë¥¼ ì²ë¦¬íë í¨ì
);모ë ëë ìì¡´ì±ì´ ì ë°ì´í¸ëë©´, ë¶ëª¨ìê² ìë¦¬ì§ ìê³ ì´ ëª¨ëì í기íê³ ì¬íê° í ì ììµëë¤. ì´ê²ì ì´ ëª¨ëì ë´ë³´ë´ê¸°ê° ìë ê²½ì°(ëë ë´ë³´ë´ê¸°ê° ë¤ë¥¸ ë°©ìì¼ë¡ ì ë°ì´í¸ëë ê²½ì°) ìë¯¸ê° ììµëë¤.
ì´ ëª¨ë(ëë ìì¡´ì±)ì íê°ìì ìì¸ê° ë°ìíë©´ errorHandlerê° ì¤íë©ëë¤.
(err, {moduleId, module}) => {}
err: ì ë²ì ì íê°í ë ë°ìí ìë¬.moduleId: íì¬ ëª¨ë id.module: íì¬ ëª¨ë ì¸ì¤í´ì¤.
module.hot: ìë¬ê° ë°ìí 모ë ì¸ì¤í´ì¤ì HMR API를 ì¬ì©íëë¡ íì©í©ëë¤. ì¼ë°ì ì¸ ìë리ì¤ë ì¤ì¤ë¡ ê·¸ê²ì ë¤ì ìë½íë ê²ì
ëë¤. ëí ë°ì´í°ë¥¼ ì ë¬í기 ìí´ dispose í¸ë¤ë¬ë¥¼ ì¶ê°íë ê²ì´ ì¢ìµëë¤. ìë¬ê° ë°ìí 모ëì ì´ë¯¸ ë¶ë¶ì ì¼ë¡ ì¤íëìì ì ììì¼ë¡, ì¼ê´ì± ìë ìíê° ëì§ ìëë¡ ì£¼ìíì¸ì. module.hot.data를 ì¬ì©íì¬ ë¶ë¶ ìí를 ì ì¥í ì ììµëë¤.module.exports: ì¤ë²ë¼ì´ëí ì ìì§ë§, íë¡ëì
모ëìì íë¡í¼í° ì´ë¦ì´ ììë ì ììì¼ë¡ 주ìíì¸ì.주ì´ì§ dependenciesì ëí ì
ë°ì´í¸ë¥¼ ê±°ë¶íì¬ 'decline' ì½ëë¡ ì
ë°ì´í¸ê° ì¤í¨íëë¡ í©ëë¤.
module.hot.decline(
dependencies // 문ìì´ ëë 문ìì´ ë°°ì´
);
// ëë
import.meta.webpackHot.decline(
dependencies // 문ìì´ ëë 문ìì´ ë°°ì´
);ì ë°ì´í¸ ë¶ê°ë¥ì¼ë¡ ìì¡´ì±ì íë그를 ì§ì í©ëë¤. ì´ê²ì ìì¡´ì± ë´ë³´ë´ê¸° ë³ê²½ì ì²ë¦¬í ì ìê±°ë ì²ë¦¬ê° ìì§ êµ¬íëì§ ìì ê²½ì° ìë¯¸ê° ììµëë¤. HMR ê´ë¦¬ ì½ëì ë°ë¼, ì´ë¬í ìì¡´ì±(ëë íì©ëì§ ìë ìì¡´ì±)ì ëí ì ë°ì´í¸ë¡ ì¸í´ ì¼ë°ì ì¼ë¡ ì ì²´ íì´ì§ê° ë¤ì ë¡ëë©ëë¤.
ìì²´ì ì¼ë¡ ì ë°ì´í¸ë¥¼ ê±°ë¶í©ëë¤.
module.hot.decline();
// ëë
import.meta.webpackHot.decline();ì ë°ì´í¸ ë¶ê°ë¥ì¼ë¡ 모ëì íë그를 ì§ì í©ëë¤. ì´ë ì´ ëª¨ëì ëë릴 ì ìë ì¬ì´ë ì´íí¸ê° ìê±°ë, ì´ ëª¨ëì ëí´ HMR ì²ë¦¬ê° ìì§ êµ¬íëì§ ìì ê²½ì° ìë¯¸ê° ììµëë¤. HMR ê´ë¦¬ ì½ëì ë°ë¼, ì´ë¬í 모ë(ëë íì©ëì§ ìì ìì¡´ì±)ì ëí ì ë°ì´í¸ë¡ ì¸í´ ì¼ë°ì ì¼ë¡ ì ì²´ íì´ì§ê° ë¤ì ë¡ëë©ëë¤.
íì¬ ëª¨ë ì½ëê° êµì²´ë ë ì¤íëë í¸ë¤ë¬ë¥¼ ì¶ê°í©ëë¤. ì´ê²ì ìì²íê±°ë ìì±í ì구 리ìì¤ë¥¼ ì ê±°íë ë° ì¬ì©í´ì¼ í©ëë¤. ì
ë°ì´í¸ë 모ëì ìí를 ì ì¡íë ¤ë©´, 주ì´ì§ data íë¼ë¯¸í°ì ì¶ê°íì¸ì. ì´ ê°ì²´ë ì
ë°ì´í¸ í module.hot.dataìì ì¬ì©í ì ììµëë¤.
module.hot.dispose((data) => {
// ë°ì´í°ë¥¼ ì 리íê³ ì
ë°ì´í¸ë 모ëë¡ ì ë¬í©ëë¤.
});
// ëë
import.meta.webpackHot.dispose((data) => {
// ë°ì´í°ë¥¼ ì 리íê³ ì
ë°ì´í¸ë 모ëë¡ ì ë¬í©ëë¤.
});ì´ ë©ìë를 í¸ì¶íë©´ íì¬ ëª¨ëì´ ë¬´í¨í ëê³ , HMR ì
ë°ì´í¸ê° ì ì©ë ë ì´ë¥¼ ìì íê³ ë¤ì ìì±í©ëë¤. ë²ë¸ì ì´ ëª¨ëì ì¼ë° ì
ë°ì´í¸ì ê°ìµëë¤. ì´ ëª¨ëì invalidate를 ìì²´ ì¹ì¸í ì ììµëë¤.
idle ìíìì í¸ì¶ëë©´, ì´ ëª¨ëì í¬í¨íë ì HMR ì
ë°ì´í¸ê° ìì±ë©ëë¤. HMRì ready ìíë¡ ë¤ì´ê°ëë¤.
ready ëë prepare ìíìì í¸ì¶ëë©´, ì´ ëª¨ëì íì¬ HMR ì
ë°ì´í¸ì ì¶ê°ë©ëë¤.
check ìíìì í¸ì¶ëë©´, ì´ ëª¨ëì ì
ë°ì´í¸ë¥¼ ì¬ì©í ì ìì ë ì
ë°ì´í¸ì ì¶ê°ë©ëë¤. ì¬ì© ê°ë¥í ì
ë°ì´í¸ê° ìì¼ë©´ ì ì
ë°ì´í¸ê° ìì±ë©ëë¤. HMRì ready ìíë¡ ë¤ì´ê°ëë¤.
dispose ëë apply ìíìì í¸ì¶ëë©´, HMRì í´ë¹ ìíìì ëì¨ í ì´ë¥¼ ì íí©ëë¤.
Conditional Accepting
모ëì ìì¡´ì±ì ë°ìë¤ì¼ ì ìì§ë§, ìì¡´ì± ë³ê²½ì ì²ë¦¬í ì ìë ê²½ì° invalidate를 í¸ì¶í ì ììµëë¤.
import { x, y } from './dep';
import { processX, processY } from 'anotherDep';
const oldY = y;
processX(x);
export default processY(y);
module.hot.accept('./dep', () => {
if (y !== oldY) {
// ì²ë¦¬í ì ìì¼ë©°, ë¶ëª¨ìê² ì ë¬
module.hot.invalidate();
return;
}
// ì²ë¦¬í ì ìì
processX(x);
});Conditional self accept
모ëì ìì²´ ìì©í ì ìì§ë§, ë³ê²½ ì¬íì ì²ë¦¬í ì ìì ë ì체를 무í¨í í ì ììµëë¤.
const VALUE = 'constant';
export default VALUE;
if (
module.hot.data &&
module.hot.data.value &&
module.hot.data.value !== VALUE
) {
module.hot.invalidate();
} else {
module.hot.dispose((data) => {
data.value = VALUE;
});
module.hot.accept();
}Triggering custom HMR updates
const moduleId = chooseAModule();
const code = __webpack_modules__[moduleId].toString();
__webpack_modules__[moduleId] = eval(`(${makeChanges(code)})`);
if (require.cache[moduleId]) {
require.cache[moduleId].hot.invalidate();
module.hot.apply();
}dispose ëë addDisposeHandler를 íµí´ ì¶ê°ë í¸ë¤ë¬ë¥¼ ì ê±°í©ëë¤.
module.hot.removeDisposeHandler(callback);
// ëë
import.meta.webpackHot.removeDisposeHandler(callback);hot module replacement íë¡ì¸ì¤ì íì¬ ìí를 ê²ìí©ëë¤.
module.hot.status(); // ë¤ì 문ìì´ ì¤ íë를 ë°íí©ëë¤...
// ëë
import.meta.webpackHot.status();| Status | Description |
|---|---|
| idle | íë¡ì¸ì¤ê° check í¸ì¶ì 기ë¤ë¦¬ê³ ììµëë¤ |
| check | íë¡ì¸ì¤ê° ì ë°ì´í¸ë¥¼ íì¸íë ì¤ì ëë¤ |
| prepare | íë¡ì¸ì¤ê° ì ë°ì´í¸ë¥¼ ì¤ë¹ ì¤ì ëë¤ (ì. ì ë°ì´í¸ë 모ë ë¤ì´ë¡ë) |
| ready | ì ë°ì´í¸ê° ì¤ë¹ëì´ ì¬ì© ê°ë¥í©ëë¤ |
| dispose | íë¡ì¸ì¤ë êµì²´ë 모ëìì dispose í¸ë¤ë¬ë¥¼ í¸ì¶í©ëë¤ |
| apply | íë¡ì¸ì¤ê° accept í¸ë¤ë¬ë¥¼ í¸ì¶íê³ ìì²´ ì¹ì¸ë 모ëì ë¤ì ì¤íí©ëë¤ |
| abort | ì ë°ì´í¸ê° ì¤ë¨ëìì§ë§, ìì¤í ì ì¬ì í ì´ì ìíì ëë¤ |
| fail | ì ë°ì´í¸ìì ìì¸ê° ë°ìíì¼ë©° ìì¤í ìíê° ììëììµëë¤ |
ì
ë°ì´í¸ë¥¼ ìí´ ë¡ëë 모ë 모ëì í
ì¤í¸íê³ , ì
ë°ì´í¸ê° ìë ê²½ì° ì´ë¥¼ apply í©ëë¤.
module.hot
.check(autoApply)
.then((outdatedModules) => {
// outdated 모ë...
})
.catch((error) => {
// ìë¬ catch
});
// ëë
import.meta.webpackHot
.check(autoApply)
.then((outdatedModules) => {
// outdated 모ë...
})
.catch((error) => {
// ìë¬ catch
});autoApply íë¼ë¯¸í°ë booleanì´ê±°ë í¸ì¶ë ë applyë©ìëì ì ë¬í optionsì¼ ì ììµëë¤.
ì
ë°ì´í¸ íë¡ì¸ì¤ë¥¼ ê³ìí©ëë¤.(module.hot.status() === 'ready'ì¸ ëì)
module.hot
.apply(options)
.then((outdatedModules) => {
// outdated 모ë...
})
.catch((error) => {
// ìë¬ catch
});
// ëë
import.meta.webpackHot
.apply(options)
.then((outdatedModules) => {
// outdated 모ë...
})
.catch((error) => {
// ìë¬ catch
});ì íì options ê°ì²´ìë ë¤ì íë¡í¼í°ê° í¬í¨ë ì ììµëë¤.
ignoreUnaccepted (boolean): íì©ëì§ ìë 모ëì ëí ë³ê²½ ì¬íì 무ìí©ëë¤.ignoreDeclined (boolean): ê±°ë¶ë 모ëì ëí ë³ê²½ ì¬íì 무ìí©ëë¤.ignoreErrored (boolean): accept í¸ë¤ë¬, ìë¬ í¸ë¤ë¬ ë° ëª¨ëì ì¬íê°íë ëì ë°ìíë ìë¬ë¥¼ 무ìí©ëë¤.onDeclined (function(info)): ê±°ë¶ë 모ëì ëí ì림onUnaccepted (function(info)): íì©ëì§ ìë 모ëì ëí ì림onAccepted (function(info)): íì©ë 모ëì ëí ì림onDisposed (function(info)): í기ë 모ëì ëí ì림onErrored (function(info)): ìë¬ ì림info íë¼ë¯¸í°ë ë¤ì ê° ì¤ ì¼ë¶ë¥¼ í¬í¨íë ê°ì²´ì
ëë¤.
{
type: 'self-declined' | 'declined' |
'unaccepted' | 'accepted' |
'disposed' | 'accept-errored' |
'self-accept-errored' | 'self-accept-error-handler-errored',
moduleId: 4, // ì§ë¬¸ì 모ë.
dependencyId: 3, // ìë¬ì ê²½ì°: accept í¸ë¤ë¬ë¥¼ ìì í 모ë id.
chain: [1, 2, 3, 4], // ê±°ë¶/íì©/íì©ëì§ ììì ê²½ì°: ì
ë°ì´í¸ê° ì íë ì²´ì¸.
parentId: 5, // ê±°ë¶ë ê²½ì°: ê±°ë¶íë ììì 모ë ic
outdatedModules: [1, 2, 3, 4], // íì©ë ê²½ì°: ì¤ëëì´ í기ë 모ë
outdatedDependencies: { // íì©ë ê²½ì°: ì
ë°ì´í¸ë¥¼ ì²ë¦¬í accept í¸ë¤ë¬ì ìì¹
5: [4]
},
error: new Error(...), // ìë¬ì ê²½ì°: throw ë ìë¬
originalError: new Error(...) // For self-accept-error-handler-errored:
// ìë¬ í¸ë¤ë¬ê° ì²ë¦¬ë¥¼ ìëí기 ì ì 모ëìì ë°ìí ìë¬.
}statusì ë³ê²½ì ìì í í¨ì ë±ë¡í©ëë¤.
module.hot.addStatusHandler((status) => {
// íì¬ ìíì ë°ì...
});
// ëë
import.meta.webpackHot.addStatusHandler((status) => {
// íì¬ ìíì ë°ì...
});ìí í¸ë¤ë¬ê° Promise를 ë°ííë©´, HMR ìì¤í
ì ê³ìí기 ì ì Promiseê° í´ê²°ë ëê¹ì§ 기ë¤ë¦½ëë¤.
ë±ë¡ë ìí í¸ë¤ë¬ ì ê±°.
module.hot.removeStatusHandler(callback);
// ëë
import.meta.webpackHot.removeStatusHandler(callback);