2

我目前正在将大型遗留 jquery-only 代码库重构为 vue 单页应用程序。在这样做的过程中,我希望将我的工作分成可管理的块,在代码中保持大部分遗留代码库的原样,并慢慢地从中提取部分和部分以重构为 vue,使用事件总线作为中介。

但是,我遇到了问题,因为旧代码在导入时会产生副作用。这些副作用是由绑定到 HTML 的运行时 jquery 事件引起的,并且创建的对象和类实例环绕其他 HTML,因为它在导入时立即建立状态。这会导致 SPA 重构出现问题,因为我希望能够离开页面然后返回到它,但是 javascript 将保持缓存而不重新加载,现在缺少所有 HTML 和状态更新,因为 vue 将删除创建状态的 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
}

有没有一种有效的方法可以从客户那里做到这一点?

4

2 回答 2

1

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

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

注意:如果您在export default动态导入的文件中使用,那么您将不得不使用newModule.default它来访问其对象。

于 2019-02-14T17:21:23.290 回答
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 网站上有一个很好的指南,介绍了 HMR 的工作原理以及如何开始

注意:AFAICT 您的旧代码在加载时会产生副作用(例如,它会破坏全局状态)。我会格外小心,因为当以确定性方式导入模块时,热重载效果最好。

于 2019-02-11T16:30:22.060 回答