4

I am using the typescript compiler to bundle my modules into one main.js file, using these settings in tsconfig.json:

"module": "system",
"out": "docs/js/main.js"

This works, so according to the SystemJS documentation, I only have to include the SystemJS production file and kickstart the app with these tags in my HTML:

<script src="js/system.js"></script>
<script>
  SystemJS.import('js/main.js');
</script> 

My app:

import { Message } from "./message";

export class App {
    constructor() {
        let demomessage = new Message("hello");
    }
}

export class Message {      
    constructor(str:string) {
        console.log(str);
    }
}

This results in this javascript code in main.js:

System.register("message", ...) {
    // message code here
});
System.register("app", ...) {
    // app code here
});

The part that I'm missing (and that's also not explained in Microsoft's always-lacking-Typescript-documentation) is how to actually start the app... How does SystemJS know which class is the starting point? Even if I just put console.log in my app it doesn't execute....

EDIT

I discovered that using system.js instead of system-production.js at least starts the process. After a lot of fiddling I got my app to start with the following code, but it looks weird and ugly. Is this how it's supposed to work???

<script src="js/system.js"></script>
<script>
  // get the anonymous scope
  System.import('js/main.js')
    .then(function() {
      // now we can get to the app and make a new instance
      System.import('app').then(function(m){
         let app = new m.App();
      })
    });
</script>
Kokodoko
  • 26,167
  • 33
  • 120
  • 197
  • Yes that's how it's supposed to work. The first import loads the bundle just to pre-populate the module registry, there's nothing within the bundle telling which module should be executed, that's the purpose of the second import. – artem Jun 02 '17 at 17:05
  • Thanks, but is there any way in which the app can start itself after being loaded? Most systemjs tutorials only mention import(js/main.js) and that seems to be enough...? – Kokodoko Jun 02 '17 at 17:15
  • There's no way if `js/main.js` is a bundle containing several modules, in other words, it has several `System.register()` calls. I'd guess all the tutorials assume it's a single module, maybe built with rollup, or just unbundled and loading all other modules separately. – artem Jun 02 '17 at 17:22
  • 1
    Thanks. The Typescript / SystemJS documentation says that you can bundle all modules in one .js file, and then use system-production.js to load everything. But apart from the fact that that doesn't work, it also doesn't mention how to instantiate the app.... it's kind of frustrating :) – Kokodoko Jun 04 '17 at 11:23

1 Answers1

5

After much head-scratching I found out the answer is more simple than expected: just load the bundle first as a regular .js file, and then you can import the app directly:

<script src="js/system.js"></script>
<script src="js/main.js"></script>
<script>
  System.import('app').then(function(module) {
    let a = new module.App();
  });
</script>
Kokodoko
  • 26,167
  • 33
  • 120
  • 197