Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HMR for SystemJS #10

Open
alexisvincent opened this issue Jan 30, 2017 · 12 comments
Open

HMR for SystemJS #10

alexisvincent opened this issue Jan 30, 2017 · 12 comments
Labels

Comments

@alexisvincent
Copy link

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
Copy link
Contributor

niieani commented Jan 30, 2017

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
Copy link

wegorich commented Jul 6, 2017

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
}
  1. 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:

  • I suppose
__webpack_require__.m[moduleId] => SystemJS.has(moduleId)
__webpack_require__.c ~  System.registry.get
          // but for webpack 
           const moduleExports = registry[moduleId].exports;
           if (typeof moduleExports === 'object') {
                callback(moduleId, moduleExports);  // <= not clear what the module Exports is, and why we push it to the callback.
           }

           // for systemjs
           const moduleExports = registry(moduleId) >????<;
           if (typeof moduleExports === 'object') {
                callback(moduleId, moduleExports); 
           }
__webpack_require__(moduleId)  => SystemJS.reload(moduleId) 

@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
Copy link

wegorich commented Jul 6, 2017

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
Copy link
Contributor

niieani commented Jul 6, 2017

@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
Copy link

wegorich commented Jul 6, 2017

@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
Copy link

wegorich commented Jul 6, 2017

@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
Copy link
Contributor

niieani commented Jul 8, 2017

@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
Copy link

wegorich commented Jul 8, 2017

@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
Copy link
Contributor

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

@wegorich
Copy link

wegorich commented Jul 10, 2017

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

  • the plugin aurelia-systemjs-hot-plugin for systemjs-hot-reloader, sends events about changes directly to HmrContext of Aurelia Loader.
  • the fork of aurelia-loader - aurelia-loader fork. Just port the code from aurelia-loader-webpack to systemjs.
  • the PR for systemjs-hot-reloader - PR - to be able to subscribe for the file changes events, especially for the aurelia-systemjs-hot-plugin.

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

@wegorich
Copy link

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
Copy link

diegohb commented Nov 16, 2017

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 ..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants