FredKSchott / esm-hmr

a Hot Module Replacement (HMR) API for your ESM-based dev server.
MIT License
413 stars 11 forks source link

provide access to the module being replaced #22

Open wighawag opened 3 years ago

wighawag commented 3 years ago

Currently with snowpack there is no way to get runtime access to the module where the js reside.

So if the import.meta.hot.accept could also provide the previousModule as argument to the callback, this would allow the reload to perform logic based on the previous module

like for example

 if (import.meta.hot) {
        import.meta.hot.accept(({module, previousModule}) => {
            for (const field of Object.keys(module)) {
                const newPrototype = Reflect.getPrototypeOf(module[field]);
                Reflect.setPrototypeOf(previousModule[field], newPrototype);
            }
       });
}
wighawag commented 3 years ago

I just realised I can do that instead: (importing the currentModule via url to get access to its fields)

async function HMR() {
    if (import.meta.hot) {
        const previousModule = await import(import.meta.url); // get access to current module
        import.meta.hot.accept(({module}: any) => {
            for (const field of Object.keys(module)) {
                const newPrototype = Reflect.getPrototypeOf(module[field]);
                Reflect.setPrototypeOf(previousModule[field], newPrototype);
            }
        });
    }
}
HMR();

That works but giving access to previous module directly in the call back is more elegant

TechAkayy commented 3 years ago

@wighawag, interesting, couldn't get the above technique to work at my end. By any chance, do you have a working example?

Does Reflect prototype get/set work as mentioned above? I tried the above and the [[FunctionLocation]] didn't really point to the updated module's exports.

wighawag commented 3 years ago

@akkayy I use it in this plugin : https://github.com/wighawag/snowpack-plugin-hmr-inject

this plugin basically injected the code above in each file specified , see : https://github.com/wighawag/snowpack-plugin-hmr-inject/blob/199bdd34a36c374c292d7664af2174b939cdb846/src/index.ts#L70-L110

TechAkayy commented 3 years ago

Thanks @wighawag. I tried the plugin and didn't had luck making it work as expected.

I have reported an issue with reproduction & video demo at the plugin's github page - https://github.com/wighawag/snowpack-plugin-hmr-inject/issues/1