Aurelia 1.0.6 with JSPM and SystemJS - Hot Module

2019-08-21 23:18发布

问题:

I have previously worked with webpack and used webpack-dev-server with gaearon/react-hot-loader that worked really well.

To achieve reload on changes I have used browser-sync with the following command that works. The proxy is the Asp.Net IIS Express:

browser-sync start --files "**/*" --proxy "https://localhost:44349/"

The problem with this is that it only works with a full page reload and what I specifically liked with react-hot-loader was that the page was not forced to reload entirely but instead could reload specific elements.

The best resource I have found until now to achieve the same in Aurelia:

https://github.com/alexisvincent/systemjs-hot-reloader/issues/102#issuecomment-314179277

According to the example gif it does exactly what I wan't:

https://github.com/wegorich/aurelia-systemjs-loader/blob/master/assets/images/demo.gif

Setup:

https://github.com/wegorich/aurelia-sysemjs-hot-plugin

Example:

https://github.com/wegorich/aurelia-systemjs-loader

Two gotchas:

You need to run:

jspm install npm:systemjs-hot-reloader-example instead of jspm install systemjs-hot-reloader-example. PR #114 has not been merged for systemjs-hot-reloader so the custom systemjs-hot-reloader-example needs to be used.

In your SystemJS config you need to add "aurelia-path": "npm:aurelia-path@1.1.1" for "npm:aurelia-hot-module-reload@0.1.0". Without this you will get a 404 for importing path. Complete:

"npm:aurelia-hot-module-reload@0.1.0": {
  "aurelia-dependency-injection": "npm:aurelia-dependency-injection@1.4.1",
  "aurelia-loader": "npm:aurelia-loader@1.0.0",
  "aurelia-metadata": "npm:aurelia-metadata@1.0.4",
  "aurelia-pal": "npm:aurelia-pal@1.8.0",
  "aurelia-templating": "npm:aurelia-templating@1.10.0",
  "aurelia-path": "npm:aurelia-path@1.1.1"
},

However when running the code I get the following error:

The systemjs-hmr polyfill must be loading after SystemJS has loaded

The scripts are loaded like this:

<script src="~/Scripts/system.js"></script>
<script src="~/src/config.js?nocache=@DateTime.Now.Ticks"></script>
<script>
    System.import('aurelia-loader-systemjs');
    Promise.all([
        System.import('aurelia-systemjs-hot-plugin'),
        System.import('systemjs-hot-reloader-example')
    ]).then(([fileChanged, connect]) => {
        connect({
            host: '//localhost:3000', fileChanged
        });
        System.import('aurelia-bootstrapper');
    });
</script>

If I load system.js after System.import('aurelia-loader-systemjs'); I get the error Uncaught ReferenceError: System is not defined.

Looking at the code that generates the error is the following:

if (!System && !!SystemJS) console.warn('The systemjs-hmr polyfill must be loading after SystemJS has loaded');

When looking at the code System is undefined and SystemJS is set. However the import is being run from System.import

I can write either SystemJS.import('aurelia-loader-systemjs'); or System.import('aurelia-loader-systemjs');. I get the same result.

https://github.com/systemjs/systemjs/issues/1351

Why is System undefined when the import is being ran?

Versions:

  • JSPM 0.16.53
  • SystemJS v0.19.27
  • Aurelia 1.0.6

I have also looked at Aurelias own hot-module-reload but it requires Webpack which we don't use.

https://github.com/aurelia/hot-module-reload

https://aurelia.io/blog/2016/12/08/big-aurelia-release-update/