How to Use Typescript with SystemJS 23

Now that Angular 2 is out and given the importance of Typescript in the Angular 2 ecosystem, it’s time to understand how to create a proper building system for our projects.

If you see any Angular 2 code example out there, you’re going to see an extensive use of the  import statement to load modules into our code like in the example below:

This code example is extracted from the Angular 2 website. It doesn’t really matter what this code does, what matters is that in the very first line they are importing the class Component  to use it in the code. So the first question that comes to my mind is: can we run this code directly in our browsers without any building process? The answer is Yes, we can if we use SystemJS.

SystemJS

Lets start this example code by creating a folder for our test project that we are going to call systemjs.

Our next step is to create two simple files that we are going to call main.ts and person.ts.

In person.ts we are just defining a simple class using the ES6 syntax that we are going to be using in main.ts.

As we said before, in order for our import statements to work, we are going to need SystemJS. We can obtain this library from npm, but before doing that, we need to create a package.json file with default values to create a list with all of our project’s dependencies.

Now, we are ready to download SystemJS.

Because SystemJS is going to handle all of the dependencies of our code, every time that one of our files import a class, a function, a variable etc., from another file, SystemJS is going to do a call to the server to get that dependency.

In our case, main.js is importing a class from person.js, so SystemJS before serving the file main.js is going to do a XHR call to the server to get person.js first. It’s now obvious that we are going to need a web server for our app, and in this case we are going to be using the npm package lite-server.

After installing the package, we can start the web server.

What happened? Turns out that when trying to invoke the lite-server package like that, our system is trying to lookup the PATH variable where all of our executable files live but in our case, the lite-server package lives inside of our own node_modules folder which is not by default in the PATH. We can fix that by creating a “script” inside package.json, that way, node is going to add by default our node_modules folder in the PATH and it’s going to be able to find the appropriate package.

Now we can run the server with the command

Loading the Dependencies in the Browser

With our dependencies in place, let’s move on and create our index.html file.

In line 6 we are loading the SystemJS in the browser. In lines 8-10 we are configuring SystemJS to use typescript as the transpiler for our code (the transpilation is going to be performed at runtime in the browser). Finally, in lines 11-13, we are importing the entry point of our application, in this case the file main.ts.

We are ready now so we can start the web server with the command npm run dev, open our browser and go to the address localhost:3000. If we open the browser’s console, we can see that something went wrong with SystemJS.

Whats missing? We told SystemJS that we are going to use typescript as the transpiler for our code but we didn’t give the browser access to the transpiler to perform the job. To fix that, we need to install the typescript transpiler locally using npm.

Then we need to go back to index.html and load the library.

At this point if we reload the browser, we are going to be able to see the string “David” in the browser’s console.

There’s one minor detail that we should fix. If we take a closer look at the file main.ts, we can see that we are defining the extension (.ts) of the dependency person.ts

When working in node, we usually don’t specify the extension of a module so to be consisten in the frontend, we should be doing that import like:

To accomplish that, we need to configure SystemJS to use the .ts extension as the default. If we see the SystemJS config API we can notice that such property exists but for some reason, we are now forced to put our typescript code inside another folder, it can’t be directly in the root folder. Although the reason to enforce that is not clear to me, having a separate folder for our “source” code is actually a good practice. So we can stop protesting against the SystemJS convention and go ahead and create a new folder called src, and move the files main.ts and person.ts to that folder.

Our now folder structure is as follow:

We can now update our index.html file to define the default extension and load the main.ts file from it’s new location.

In lines 10-13 we are defining the default extensions of our files using the package property. Notice that the keys right under the package property should match any of our folders, in this case we are referencing our src folder.

On line 17 we are changing the location of our main file and deleting the explicit mention to the .ts extension. Similarly, we can modify our main.ts file to delete the extension of the dependency.

If we go back to see our browser’s console we can see that everything is working as expected with a more concise import syntax.

23 thoughts on “How to Use Typescript with SystemJS

  1. Reply bellalevy Feb 23,2016 3:12 pm

    I highly recommend JSPM which is a sub project of system.js its way more powerful
    Checkout the Ultimate Angular 2 Boorstrap App: @ http://ng2.javascriptninja.io
    Source@ https://github.com/born2net/ng2Boilerplate

    Regards,

    Sean
    ================

    • Reply David Barreto Feb 23,2016 6:59 pm

      Thanks for the recommendation Sean. I’m actually trying to decide the best build system for an angular 2 project with typescript. Right now I’m exploring webpack as well to see if it’s potentially simpler to implement than gulp + systemjs. I will take a look at jspm for sure.

  2. Reply jupo Apr 17,2016 6:27 am

    nice, thanks for the article! How do you bundle all the source to a single file for production?

    • Reply David Barreto Apr 18,2016 2:02 pm

      For that you might have to use webpack instead of systemjs

      • Reply Jose Lee Apr 18,2016 2:34 pm

        I also noticed when I tried this out yesterday, that typescript.js is nearly 4 megabytes in size! That’s simply too large in my opinion. I know that tsc (typescript compiler) can output JS files compatible with the SystemJS module system. If the TS is pre-transpiled, I assume we wouldn’t need include typescript.js… do you know how to bootstrap such files? I’ve been trying this all day to no avail.

    • Reply Maciej May 6,2016 12:19 pm

      Why bundling? Sole purpose of SystemJS is that it can read modules *as they are*.

      You can load CommonJS, ES6 and AMD.

      Inability of doing so spawned the need of bundlers into-one-massive-production file.

      • Reply gilesroadnight Nov 21,2016 9:37 am

        If you have a large project then there could be hundreds of network calls to load all of the js files. This is unacceptable in production over possibly a mobile connection.
        If using http2 this is less of a problem as many small network requests are much cheaper.

  3. Reply Franz Zemen May 1,2016 3:27 pm

    For someone learning TypeScript, angular2 and everything in between, I’ve been racking my brain around module loading. This article goes a long way to clear things up (at least with SystemJS).

    Thx

  4. Reply Akseli Koskinen May 11,2016 5:40 am

    Thanks! This was very useful. I’ve been reading ng-book 2 and found systemjs and modules very confusing

  5. Reply mallik Jun 24,2016 3:52 pm

    This is very useful and appreciate the way it was put together. In continuation to this tutorial, I like to see generating ‘build’ for production using systemJS. Look forward to it.

    Thanks

  6. Pingback: How to Use Typescript with SystemJS ← David Barreto - angular.org.il

  7. Reply Santosh Kumar Jul 6,2016 7:22 am

    In a typical example (found on internet)

    System.config({
    packages: {
    app: {
    format: ‘register’,
    defaultExtension: ‘js’
    }
    }
    });

    The “app” folder is storing source files with extension “js”. Could you tell me about “register” property there

    • Reply David Barreto Jul 11,2016 7:03 pm

      To be honest with you I don’t know. Since I wrote this post I started using webpack instead of systemjs and never looked back.

  8. Reply Mani Jul 11,2016 9:39 am

    Hi,I was trying the same in visual studio but ended up in getting system is undefined error.I have copied the system,js content in URL(https://npmcdn.com/systemjs@0.19.31/dist/system.js) to my local file system.js and referred it in my index.html.

    Whereas this approach works well in plunker. Anyone tried this appraoch in visual studio

    • Reply David Barreto Jul 11,2016 7:00 pm

      I don’t know exactly why is failing for you but I can tell you that my IDE of choice when working with these technologies is Visual Studio Code and it’s amazing.

  9. Reply Uma Shankar Aug 8,2016 12:25 am

    How to config external modules ? like ‘rxjs’ . I mean how to tell System loader to find external library file in System.config ?

  10. Reply Sean Tobin Sep 22,2016 10:56 am

    did you mean npm init –force instead of npm install –force ?

  11. Reply sachin Nov 5,2016 1:40 am

    I must tell you that this one is really nice article…. I have just started anuglarjs2, I was looking how initial process is working and this article give me the proper answer.

  12. Reply gilesroadnight Nov 21,2016 9:39 am

    A nice concise article but I would be interested in how you then productionise this.
    I suppose all you need to do is remove the tsc script tag and change the default extension.
    Do you have a different index.html for this or modify the same one with some sort of build job?

Leave a Reply