【问题标题】:Force Reload on Webpack Async Import强制重新加载 Webpack 异步导入
【发布时间】:2019-06-23 21:20:09
【问题描述】:

我目前正在将大型遗留 jquery 代码库重构为 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
}

客户有没有有效的方法来做到这一点?

【问题讨论】:

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


    【解决方案1】:

    热模块更换 (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 的工作原理以及如何开始

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

    【讨论】:

    • 这里的问题是 webpack 似乎没有任何文档说明如何说模块已更改,即使它没有更改。我已经查看了那里的文档,但我没有找到从服务器实际请求新副本的方法。我只是错过了一些简单的东西吗?
    • 由于副作用,我已经考虑了重置全局状态。这种热重载之所以重要,是为了从根本上快速修复模块化这些副作用,以便在正确的时间重新启动。
    • 开发服务器(理论上)正在监视您的文件是否有更改,因此它应该检测模块何时更改。你能提供你的 webpack 配置吗?
    • 这又是我想要做的。我不想在模块更改时重新加载文件。我想重新加载文件,以便在没有重大重构的情况下重新运行 javascript 副作用。我想在客户每次去某条路线时都这样做。不是当服务器上发生某些事情时。我想要热重新加载,但用于重新加载脚本以再次运行的生产用途,而不是对服务器上更改的文件做出反应。
    • 我想我可能遇到了类似的问题。在我注释掉if (module.hot) { module.hot.accept()} 之后,我的 jquery 代码仅在热重新加载时执行一次,之后它不会再次重新加载它。有人知道为什么会这样吗?我需要以某种方式修改热重载功能吗?
    【解决方案2】:

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

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

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

    【讨论】:

    • 这听起来很有希望!我之前尝试过弄乱 require.resolve 缓存,但我会使用 await require 而不是 webpack 异步导入功能再试一次,尽管我不知道它们是否只是具有不同语法的相同功能
    • 它们或多或少相同,但语法不同。 webpack.js.org/api/module-methods/#commonjs
    • 我觉得这种方法应该行得通,但我们一直在苦苦挣扎,即使感觉应该这样做,它似乎也无法让它重新加载。不过感谢您的帮助!
    猜你喜欢
    • 2014-03-30
    • 2018-08-16
    • 1970-01-01
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 2012-06-18
    相关资源
    最近更新 更多