在动态导入中使用 Parcel.js 的 HMR

HMR with Parcel.js within dynamic imports

我有一个简单的 Parcel.js 2.0 设置,以 main.js 文件作为起点:

import('./components/faqs/faqs.js').then(function(Faqs){

  Faqs.init()  

})

当 运行 parcel watch - 我发现 main.js 文件 HMR 的变化如预期的那样,但在 init 函数中对链接的 faqs.js 的变化没有,并且需要页面刷新。

如果我采用同步方法,例如:

import init from'./components/faqs/faqs.js'

init()  

然后 HMR 按预期工作,刷新 faqs.js 的任何更改。这是 Parcel 的 HMR 的预期行为吗?

我对此进行了调试,下面是通过此示例快速描述 Parcel HMR 中当前发生的情况:

  1. 您第一次加载 main.js,它会动态导入并加载 faqs.js
  2. 您对 faqs.js 进行了更改,parcel 向浏览器发送了一个 websocket 消息,通知它需要重新加载以 faqs.js 开头的包。下载并执行更新的包代码,包括 init() 函数的新定义。 faqs.js 中的任何全局副作用也将重新 运行。到目前为止,还不错。
  3. 然而,您可能期望的是来自 main.js.then 回调实际上 运行s init函数也重运行s。这不会发生,因为 parcel 独立处理不同的动态包。

IMO,这似乎是当前在 Parcel2 中实现 HMR 的一个粗糙边缘 - 我将用我发现的内容提交一个错误,以便我们考虑可能改进它。

然而,与此同时,您可以通过向 module.hot.accept 提供回调来自行解决该问题,这将在开发模式下由 parcel 注入(请参阅 documentation)。例如,您可以将其添加到 faqs.js:

// "module.hot" is injected by parcel in development mode.
// This check will ensure that this code _only_ runs in this context
// (e.g. it won't affect production)
if (module.hot) {
   // The callback provided to "module.hot.accept" will be run whenever
   // parcel sends a new version of `faqs.js` to the browser in development.
   module.hot.accept(() => {
      // Actually run the new version of your init function.
      init()
   })
}