在Webpack异步导入上强制重新加载

时间:2019-01-30 14:45:50

标签: javascript vue.js webpack single-page-application hot-reload

我目前正在研究从大型的仅基于jquery的旧代码库到vue单页应用程序的重构。这样做时,我希望将工作分解成可管理的块,按原样在代码中维护许多旧代码库,并慢慢地将其中的各个部分从中拉出,以重构为vue,并使用事件总线作为中介。

但是,由于遗留代码在导入时会产生副作用,因此我遇到了问题。这些副作用是由绑定到HTML的运行时jquery事件以及在导入时立即建立状态的其他HTML环绕而创建的对象和类实例引起的。这会导致SPA重构出现问题,因为我希望能够从页面导航离开然后返回到页面,但是javascript仍将保留缓存并且不会重新加载,由于vue已删除了,因此现在缺少所有HTML和状态更新html创建状态,然后在重新渲染上添加新的html。

我正在寻找解决此问题的最佳方法,以免我不得不两次重构代码-一次通过init调用进入模块化导入,然后进入一种反应式模块化Vue范例。为此,我想弄清楚如何使用Webpack的异步块导入来重新加载代码块。我知道这是有可能的,因为webpack会对文件进行热重载。我本质上是想在访问特定路由时强制对某些导入进行热重载。

这就是我想要做的:

async function reloadLegacyCodeOnSPARoutingChange(){
    cleanAnyPolutingGlobals();
    const initLegacyCode = await import(`./LegacyCode.js`); //somehow force it to reload this as if it were a fresh import
    let thingId = this.$store.state.thingPage.thingId;
    await initLegacyCode(thingId);
    await EventBus.$emit('initLegacyCodeState'); //apply the properties from our reactive state system
}

从客户那里有有效的方法吗?

2 个答案:

答案 0 :(得分:0)

热模块替换(HMR)并不是某种黑魔法(尽管我认为是)。想象一下一个客户机/服务器体系结构,其中客户机(您的应用程序)询问服务器(启用了HMR的Webpack)在您要导入的模块中是否有任何更改。如果是这样,它将重新加载模块。

// Add this to the file you are initially loading
if (module.hot) {
  module.hot.accept('./LegacyCode.js', async function() {
    console.log('Accepting the updated LegacyCode.js module!');
    let thingId = this.$store.state.thingPage.thingId;
    await initLegacyCode(thingId);
    await EventBus.$emit('initLegacyCodeState');
  })
} 

webpack网站上有great guide,介绍HMR的工作原理和入门方法

注意:遗留代码在加载时会产生副作用(例如,它会使全局状态混乱)。我会特别小心,因为以确定性方式导入模块时,热重装效果最佳。

答案 1 :(得分:0)

如果标志useFresh为true,则可以动态导入模块并将其从缓存中删除。

async function getFile (useFresh) {
    try {
        useFresh && delete require.cache[require.resolve('./Test')];
    } catch (err) { }
    let newModule = await require('./Test');
}

注意:如果要在动态导入的文件中使用export default,则必须使用newModule.default来访问其对象。