aurelia / hot-module-reload

Core functionality for Aurelia's hot-module-reolad (HMR) capabilities, which is shared by all loaders and tools.
MIT License
25 stars 8 forks source link

HMR for SystemJS #10

Open alexisvincent opened 7 years ago

alexisvincent commented 7 years ago

Hi Guys,

I'm trying to work out how to get Aurelia HMR support into systemjs-hmr, and by extension systemjs-hot-reloader.

But I'm unsure of what it would take other then standard hmr. This project seems to reimplement a module registry?

niieani commented 7 years ago

No such reimplementation here. It should be pretty simple to add the required hooks via the SystemJS interface. I don't have capacity to do this, however any PRs are welcome. All that's most probably needed is a PR to aurelia/loader, adding similar capabilities as outlined here in the loader-webpack: https://github.com/aurelia/loader-webpack/blob/1e318399ad40290185296197839149aa85148bd9/src/aurelia-loader-webpack.ts#L113-L132.

wegorich commented 7 years ago

I'm trying to implement aurelia-systemjs-loader based on (https://github.com/aurelia/loader-default) for HMR module, but as for me it's not so clear what the aurelia-webpack loader do (https://github.com/aurelia/loader-webpack).

The stack I use: https://github.com/alexisvincent/systemjs-hot-reloader - it provide two points of trues:

  1. As I suppose the place where I have to run HMR methods to force the Aurelia to reload the module

    export const __unload = () => {
    console.log('Unload something (unsubscribe from listeners, disconnect from socket, etc...)')
    // your container node
    }
  2. Check the module was loaded, and force Aurelia to reload the module.

/**
 * You can import the previous instance of your module as you would any other module.
 * On first load, module == false.
 */
import { module } from '@hot'

/**
 * Since all exports of the previous instance are available, you can simply export any state you might want to persist.
 *
 * Here we set and export the state of the file. If 'module == false' (first load),
 * then initialise the state to {}, otherwise set the state to the previously exported
 * state.
 */
export const _state = module ? module._state : {}

https://github.com/capaj/chokidar-socket-emitter - to connect to the browser-sync https://github.com/aurelia/hot-module-reload - try current module, to reload the modules,

The aurelia/hot-module-reload still a black box for me, would be glad for any information about API needs to be used in the aurelia loader.

I'm not so familiar with webpack, so I start to compare line by line with default-loader, to find the places I have to reimplement:

  1. https://github.com/aurelia/loader-webpack/blob/1e318399ad40290185296197839149aa85148bd9/src/aurelia-loader-webpack.ts#L65-L88
  2. https://github.com/aurelia/loader-webpack/blob/master/src/aurelia-loader-webpack.ts#L91-L100
  3. https://github.com/aurelia/loader-webpack/blob/master/src/aurelia-loader-webpack.ts#L104-L137

And I stuck for now with system js alias for:

@niieani, could you please explain the scenario we have to implement in aurelia/loader to be able use aurelia-hmr modue with any custom loader, let's skip systemjs for a while. Any information even in general would be helpfull

wegorich commented 7 years ago

For now I have aurelia-systemjs-loader that didn't launch any methods after systemjs reload module, have no idea what to do next :(

Updates:

Found the way how to receive SystemJS new module object, and how to trigger the methods in the aurelia-loader. But two questions:

  1. How can I update templates runtime
  2. How can I update JS runtime

Using the aurelia/hot-module-reload?

niieani commented 7 years ago

@wegorich see this main class: https://github.com/aurelia/hot-module-reload/blob/master/src/aurelia-hot-module-reload.ts#L41

It contains 3 methods: handleModuleChange, handleViewChange and reloadCss. Each can be used to hot reload a module of given type, once it is removed from the cache of the AureliaLoader instance, and a new instance is available for loading.

You'll need to fork and edit aurelia-loader to add functionality that removes stale modules from its cache. You can see how this is done in aurelia-loader-webpack, since both have a relatively similar structure.

wegorich commented 7 years ago

@niieani thanks. Will dive in this methods.

if(window.__reloaded) {
                    if (!this.hmrContext) {
                        // Note: Please do NOT import aurelia-hot-module-reload statically at the top of file.
                        //       We don't want to bundle it when not using --hot, in particular in production builds.
                        //       Webpack will evaluate the `if (module.hot)` above at build time 
                        //       and will include (or not) aurelia-hot-module-reload accordingly.
                        const { HmrContext } = require('aurelia-hot-module-reload');
                        this.hmrContext = new HmrContext(this);
                    }

                    await this.hmrContext.handleViewChange(address);
                }

I did pretty similar as at the aurelia-loader-webpack, but receive aurelia-hot-module-reload.js:278 Something's gone wrong, no original ViewFactory?!

error.

wegorich commented 7 years ago

@niieani Still a bit confusing.

So I reload js && html client side module then I trigger:

if (defaultHMR && this.hmrContext) {
    this.hmrContext.handleModuleChange(address);
}

Nothing happened.

niieani commented 7 years ago

@wegorich did you implement logic for cleaning the cache of modules in your fork of aurelia-loader? If you send me a link to your fork, I can have a look if I see any problems.

wegorich commented 7 years ago

@niieani yep, aurelia-loader-systemjs, I made it works in the sandbox. Test only HTML and JS reloads.

I'll make the beautiful fork of aurelia-loader in Monday 👍

EisenbergEffect commented 7 years ago

Please share a bit about the changes you needed to make, maybe they can be officially incorporated somehow or built into a plugin.

wegorich commented 7 years ago

Yeah, I spend the day and create simple modules we can use. No need to change the aurelia-hot-module-reload it works fine. Not sure about ViewSlots...

So I did

Not sure what to do with aurelia-loader next. So publish it as aurelia-loader-systemjs to the npm.

wegorich commented 7 years ago

Ah my mistake, play with aurelia-systemjs-hot-plugin and found that I have to reimplement the aurelia-webpack-plugin. Hope aurelia-hot-module-reload handle all this cases, but it should be done manually... Heh.

diegohb commented 6 years ago

Does this mean that the description of this package that says HMR works across all loaders is incorrect ? or are these comments dated and there's no need for aurelia-systemjs-hot-plugin now ?

I don't have HMR confgured with SystemJS now but I'm using aurelia + systemjs + ts... would like to setup HRM in the easiest/simplest way possible ..