如果通过 热模块替换 使用 HotModuleReplacementPlugin
启用了热模块替换,则其接口将公开在 module.hot
属性以及 import.meta.webpackHot
属性下。请注意,只有 import.meta.webpackHot
可用于 严格 ESM。
通常,用户会检查接口是否可访问,然后开始使用它。例如,以下是如何 accept
更新的模块
if (module.hot) {
module.hot.accept('./library.js', function () {
// Do something with the updated library module...
});
}
// or
if (import.meta.webpackHot) {
import.meta.webpackHot.accept('./library.js', function () {
// Do something with the updated library module…
});
}
支持以下方法...
接受给定 dependencies
的更新并触发 callback
以对这些更新做出反应,此外,您还可以附加一个可选的错误处理程序
module.hot.accept(
dependencies, // Either a string or an array of strings
callback, // Function to fire when the dependencies are updated
errorHandler // (err, {moduleId, dependencyId}) => {}
);
// or
import.meta.webpackHot.accept(
dependencies, // Either a string or an array of strings
callback, // Function to fire when the dependencies are updated
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 // Function to handle errors when evaluating the new version
);
// or
import.meta.webpackHot.accept(
errorHandler // Function to handle errors when evaluating the new version
);
当此模块或依赖项更新时,此模块可以被丢弃并重新评估,而无需通知父级。如果此模块没有导出(或导出以其他方式更新),则此操作很有意义。
当此模块(或依赖项)的评估抛出异常时,将触发 errorHandler
。
(err, {moduleId, module}) => {}
err
: 评估新版本时的错误。moduleId
: 当前模块 ID。module
: 当前模块实例。module.hot
: 允许使用出错模块实例的 HMR API。一个常见的场景是再次自我接受它。添加一个 dispose 处理程序来传递数据也是有意义的。请注意,出错的模块可能已经部分执行,因此请确保不要进入不一致的状态。您可以使用 module.hot.data
来存储部分状态。module.exports
: 可以被覆盖,但要小心,因为属性名称在生产模式下可能会被混淆。拒绝给定 dependencies
的更新,强制更新失败并显示 'decline'
代码。
module.hot.decline(
dependencies // Either a string or an array of strings
);
// or
import.meta.webpackHot.decline(
dependencies // Either a string or an array of strings
);
将依赖项标记为不可更新。当更改此依赖项的导出无法处理或处理尚未实现时,此操作很有意义。根据您的 HMR 管理代码,对这些依赖项(或其未接受的依赖项)的更新通常会导致页面完全重新加载。
拒绝自身更新。
module.hot.decline();
// or
import.meta.webpackHot.decline();
将此模块标记为不可更新。当此模块具有不可逆的副作用或尚未为此模块实现 HMR 处理时,此操作很有意义。根据您的 HMR 管理代码,对此模块(或未接受的依赖项)的更新通常会导致页面完全重新加载。
添加一个处理程序,当当前模块代码被替换时执行。这应该用于删除您已声明或创建的任何持久资源。如果您想将状态转移到更新的模块,请将其添加到给定的 data
参数中。更新后,此对象将在 module.hot.data
中可用。
module.hot.dispose((data) => {
// Clean up and pass data to the updated module...
});
// or
import.meta.webpackHot.dispose((data) => {
// Clean up and pass data to the updated module...
});
调用此方法将使当前模块失效,当应用 HMR 更新时,会将其销毁并重新创建。这就像此模块的正常更新一样。invalidate
不能被此模块自身接受。
在 idle
状态下调用时,将创建一个包含此模块的新 HMR 更新。HMR 将进入 ready
状态。
在 ready
或 prepare
状态下调用时,此模块将被添加到当前 HMR 更新中。
在 check
状态下调用时,此模块将在更新可用时被添加到更新中。如果更新不可用,它将创建一个新的更新。HMR 将进入 ready
状态。
在 dispose
或 apply
状态下调用时,HMR 将在退出这些状态后将其拾取。
条件接受
模块可以接受依赖项,但当依赖项的更改无法处理时,可以调用 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) {
// This can't be handled, bubble to parent
module.hot.invalidate();
return;
}
// This can be handled
processX(x);
});
条件自接受
模块可以自接受,但当更改无法处理时,可以使自身失效
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();
}
触发自定义 HMR 更新
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);
// or
import.meta.webpackHot.removeDisposeHandler(callback);
检索热模块替换过程的当前状态。
module.hot.status(); // Will return one of the following strings...
// or
import.meta.webpackHot.status();
状态 | 描述 |
---|---|
idle | 该过程正在等待调用 check |
检查 | 该过程正在检查更新 |
prepare | 该过程正在为更新做准备(例如,下载更新的模块) |
ready | 更新已准备就绪并可用 |
dispose | 该过程正在调用将被替换的模块上的 dispose 处理程序 |
应用 | 该过程正在调用 accept 处理程序并重新执行自接受的模块 |
abort | 更新已中止,但系统仍处于先前状态。 |
失败 | 更新引发异常,系统状态已受损。 |
测试所有已加载的模块以获取更新,如果存在更新,则应用
它们。
module.hot
.check(autoApply)
.then((outdatedModules) => {
// outdated modules...
})
.catch((error) => {
// catch errors
});
// or
import.meta.webpackHot
.check(autoApply)
.then((outdatedModules) => {
// outdated modules...
})
.catch((error) => {
// catch errors
});
autoApply
参数可以是布尔值或options
,在调用时传递给apply
方法。
继续更新过程(只要module.hot.status() === 'ready'
)。
module.hot
.apply(options)
.then((outdatedModules) => {
// outdated modules...
})
.catch((error) => {
// catch errors
});
// or
import.meta.webpackHot
.apply(options)
.then((outdatedModules) => {
// outdated modules...
})
.catch((error) => {
// catch errors
});
可选的options
对象可以包含以下属性
ignoreUnaccepted
(布尔值):忽略对未接受模块所做的更改。ignoreDeclined
(布尔值):忽略对已拒绝模块所做的更改。ignoreErrored
(布尔值):忽略在接受处理程序、错误处理程序和重新评估模块时抛出的错误。onDeclined
(函数(信息)):已拒绝模块的通知程序onUnaccepted
(函数(信息)):未接受模块的通知程序onAccepted
(函数(信息)):已接受模块的通知程序onDisposed
(函数(信息)):已处置模块的通知程序onErrored
(函数(信息)):错误的通知程序info
参数将是一个包含以下某些值的 对象
{
type: 'self-declined' | 'declined' |
'unaccepted' | 'accepted' |
'disposed' | 'accept-errored' |
'self-accept-errored' | 'self-accept-error-handler-errored',
moduleId: 4, // The module in question.
dependencyId: 3, // For errors: the module id owning the accept handler.
chain: [1, 2, 3, 4], // For declined/accepted/unaccepted: the chain from where the update was propagated.
parentId: 5, // For declined: the module id of the declining parent
outdatedModules: [1, 2, 3, 4], // For accepted: the modules that are outdated and will be disposed
outdatedDependencies: { // For accepted: The location of accept handlers that will handle the update
5: [4]
},
error: new Error(...), // For errors: the thrown error
originalError: new Error(...) // For self-accept-error-handler-errored:
// the error thrown by the module before the error handler tried to handle it.
}
注册一个函数来监听status
的变化。
module.hot.addStatusHandler((status) => {
// React to the current status...
});
// or
import.meta.webpackHot.addStatusHandler((status) => {
// React to the current status...
});
请记住,当状态处理程序返回一个Promise
时,HMR 系统将等待Promise
解析,然后再继续。
删除已注册的状态处理程序。
module.hot.removeStatusHandler(callback);
// or
import.meta.webpackHot.removeStatusHandler(callback);