我目前正在研究从大型遗留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
}
有没有一种有效的方法从客户端做到这一点?
热模块替换(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');
})
}
网站上有一个关于HMR如何工作以及如何开始的great guide
注意:AFAICT您的遗留代码在加载时会产生副作用(例如,它会影响全局状态)。我会特别小心,因为当以确定的方式导入模块时,热重新加载最有效。
如果标志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
来访问其对象。