Skip to content

Instantly share code, notes, and snippets.

@robwormald
Last active January 5, 2022 21:21
Show Gist options
  • Save robwormald/429e01c6d802767441ec to your computer and use it in GitHub Desktop.
Save robwormald/429e01c6d802767441ec to your computer and use it in GitHub Desktop.

Angular2 + JSPM cheat sheet

First time setup

  • install jspm beta: npm install -g jspm@beta
  • set up your project: jspm init
  • install dependencies: jspm install angular2 reflect-metadata zone.js es6-shim

This will create a jspm_packages folder, and a config.js file.

Open the config.js file - this file manages options for the System.js loader - tweak it as appropriate

System.config({
  "baseURL": "/",
  "defaultJSExtensions": true,
  "transpiler": "typescript",
  //add this if using typescript
  "typescriptOptions":{
    "module":"commonjs",
    "emitDecoratorMetadata": true
  },
  //add this if using traceur
  "traceurOptions": {
    "annotations" : true,
    "memberVariables" : true,
    "types" : true
  },
  //add this if using babel
  "babelOptions": {
    "optional" : ["runtime"],
    "stage" : 1
  },
  "paths": {
    "github:*": "jspm_packages/github/*",
    "npm:*": "jspm_packages/npm/*",
    //this lets us use app/ for our package as a sort of virtual directory
    "app": "src"
  },
  //this configures our app paths
  "packages": {
    "app": {
      "main": "main",
      "defaultExtension": "js" //or "ts" for typescript
    }
  }
});

Create a new src directory, and a main.js or main.ts file inside of it:

//import deps
import 'zone.js';
import 'reflect-metadata';
//you may need es6-shim if you get an error relating to list.fill
//import es6-shim;

//if using traceur compiler:
import {
  ComponentAnnotation as Component,
  ViewAnnotation as View,
  bootstrap
} from 'angular2/angular2';
//OR
//if using babel or typescript compiler:
import {
  Component,
  View,
  bootstrap
} from 'angular2/angular2';

//create a simple angular component
@Component({
  selector: 'test-app'
})
@View({
  template: '<h4>Hello {{name}}</h4>'
})
class TestApp {
  name: string;
  constructor(){
    this.name = 'Angular2';
    setTimeout(() => {
      this.name = 'Angular2!!!'
    },1500);
  }
}

//start our app
bootstrap(TestApp);

Create an index.html page:

<html>
<head>
    <title>Demo App</title>
    <!-- systemJS loader and config -->
    <script src="jspm_packages/system.js"></script>
    <script src="config.js"></script>
</head>
<body>
    <!-- our angular2 component -->
    <test-app>
        Loading...
    </test-app>
    
    <!-- import and run our app -->
    <script>
      System.import('app');
    </script>
</body>
</html>

Start a local server http-server or python -m SimpleHTTPServer and open localhost:8080 in your browser.

Bundling Options

  • jspm bundle app dist/main.js --inject - outputs a single bundle and adds it to the config file, SystemJS will load it instead of 11ty files.
  • jspm bundle app dist/main.min.js --minify - outputs a minified single bundle you can include in a script tag after System.js and your config.
  • jspm bundle-sfx app dist/main.sfx.js - outputs a single file you can include without any other dependencies.
@evanplaice
Copy link

@SonofNun15 Zone.js must be loaded first (ie even before System.js), and is required for data binding in Angular2.

It works as a higher order function wrapper for all events. Angular2's uses it to wrap all one-way/two-way bindings so it can catch changes as they occur and fire a digest cycle. As such, Angular2 event binding won't work without it.

@CallMeLaNN
Copy link

I'm testing it with beta.0 now. Finally I understand what is going on. The issue with reflect-metadata and Zone now fixed by just in one conclusion:

Put the most important js that does not require System or umd simply in script tag before jspm. Anything else that using System or umd can be import-ed on your app script.

Explanation:

The angular2-polyfills.js contain script for zone.js and reflect-metadata. In the documentation shows the script tag ordered above the system.js as shown below.
Even though we can import normal js using jspm, zone.js is not the case. So we follow the script tag sequence in the Angular2 documentation.

Based on the 5min QuickStart:

Run jspm init and jspm install angular2 rxjs.
Change the script index.html from this:

<script src="node_modules/es6-shim/es6-shim.js"></script><!-- optional -->
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>

to this:

<script src="node_modules/es6-shim/es6-shim.js"></script><!-- optional -->
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<!-- The Rx.js and angular2.dev.js has been moved to use jspm -->
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>

Import the rxjs. TypeScript example in boot.ts:

import 'rxjs';

Now everything is working including jspm bundling. Furthermore any changes on next beta release is easy to be updated, just change the script tag starting from the system.src.js. Hopefully Angular2 will support jspm on next beta release.

@sivabudh
Copy link

sivabudh commented Jan 6, 2016

@CallMeLaNN, kindly could you please share with me a bit why using JSPM is better? I just finished the ng2's 5 minute quickstart, and want to understand how JSPM will help me.

Thanks!

@CallMeLaNN
Copy link

@sivabudh, it is based on use case and personal preference. Try to familiarize with JavaScript module loader, SystemJs, AMD, CommonJs, then see the difference between JSPM, Bower, Webpack, etc. It is not apple to apple comparison. It has its own motivation and features. I use JSPM because it is a package manager for universal module loader.

@rubyboy
Copy link

rubyboy commented Jan 7, 2016

@sivabudh, @CallMeLaNN, one of the main benefits of using JSPM is having all dependencies managed by it (NPM/Github/Custom) and bringing them in as needed with imports. I prefer avoiding having any dependencies in the index.html and bring them all in with imports ( and JSPM install ). It's quite easy then to bundle it all in one SFX and have a single script import in the index.html (or split to several bundles). JSPM Rocks! :)

@SonofNun15, adding this import at the top of the main bootstrap script worked for me:
import "zone.js/dist/zone.min.js";

See example here: angular2-simple-list/app/main.ts
Or in this angular2 tutorial

@playground
Copy link

Sorry, I haven't been here in a few days.

I did finally get beta.0 to work by including zone.js in script tag before SystemJS. The reason it was failing for me was that one of the component was importing zone.js. I think it's just a timing issue. commenting out the import, fix the issue.

@mgamsjager
Copy link

So far so good everything seems to work. Last issue is the amount of single js file that get loaded each time.(jspm/jspm-cli#482)

It works so far that I can load the bundle with --inject but that means I can't really change any file which voids this option.

When I try what is suggested in the issue (jspm bundle 'src/js//*' - '[src/js//*]' dev-deps.js --inject) JSPM still reloads all files.
Anyone got this working yet?

@brendanalexdr
Copy link

Anybody having trouble with minifying angular2 jspm bundles? I am able to create a self executing bundle that works unminified. However, after minification the code breaks. I get

"RangeError: Maximum call stack size exceeded"

@brendanalexdr
Copy link

Update: I have solved my problem by setting "mangle: false" in the jspm bundle options. The default is apparently "true"

@PhilippSoehnlein
Copy link

I was able to configure SystemJs with Angular2 (beta.1) without any script tags (with the exception of SystemJS itself and the SystemJS config).

<script src="js/lib/system.js"></script>
<script src="js/systemjs-config.js"></script>
<script>
  System.import("app/main").then( null, console.error.bind( console ) );
</script>
System.config({
  // …
  meta: {
    'angular2/*': {
      deps: [ 'zone.js/dist/zone.min.js', 'reflect-metadata' ],
    }
  },
  // …
});

My TS-code can then just import {Component, View} from 'angular2/core'; and start doing Angular stuff without any other boilerplate within the TS files.

@eliezerreis
Copy link

Unfortunately after 2 or 3 days trying to include JSPM to work with angular2 I give up. Lots of path, meta, and other ***** to configure and still give lots of compilations problems. Following the 5 minutes tutorial from angular2 is too easy and jspm includes 3 days of configs that never ends.

@ryanlangton
Copy link

If you include angular2-polyfills (which I had to do to get it to work), you do not need reflect-metadata or zone.js in your initial .js file. Remove these lines:

// you don't need these lines!
import 'zone.js';
import 'reflect-metadata';
import 'es6-shim';

So you should only have 3 script tags in your root html, the rest should be loaded by sytem.js w/ jspm.

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/2.0.0-beta.2/angular2-polyfills.js"></script>
<script src="jspm_packages/system.js"></script>-->
<script src="config.js"></script>

@rubyboy
Copy link

rubyboy commented Feb 8, 2016

Here's my workflow for new projects with angular2+JSPM+TS. It requires no extra script tags and no need to maintain versions outside of JSPM.

jspm init

(When asked about transpiler, select "typescript")

jspm install angular2 reflect-metadata zone.js rxjs
mkdir app

Add the following to your config.js:

   typescriptOptions: {
    "module": "commonjs",
    "emitDecoratorMetadata": true
  },
  packages: {
    "app": {
      "main": "main",
      "defaultExtension": "ts"
    }
  },

index.html:

<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
<my-app>Loading...</my-app>
<script src="jspm_packages/system.js"></script>
<script src="config.js"></script>
<script>
    System.import("app");
</script>
</body>
</html>

app/main.ts:

import "zone.js";
import "reflect-metadata";
import {bootstrap} from "angular2/platform/browser";
import {App} from "./app";
bootstrap(App);

app/app.ts

import {Component} from "angular2/core"
@Component({
    selector: "my-app",
    template: `test`
})
export class App { }

@Olgagr
Copy link

Olgagr commented Feb 11, 2016

Does anybody has problem with rxjs@5.0.0-beta.2/observable/fromPromise.js file ? I'm getting 404 error, when systemjs is trying to load this file (I'm using angular2.beta5)

---- edit -----
This is a bug in Angular 2 beta 5: angular/angular#5643

@sandric
Copy link

sandric commented Feb 18, 2016

@rubyboy Hm, I'm getting this with your config:

warn Error on download for github:systemjs/plugin-json
     Error: getaddrinfo ENOTFOUND api.github.com api.github.com:443
         at errnoException (dns.js:26:10)
         at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:77:26)

err  Error downloading github:systemjs/plugin-json.

warn Installation changes not saved.

@sandric
Copy link

sandric commented Feb 18, 2016

Well, IDK why, but that resolved somehow, so don't mind, sorry.

Anyone can help me understanding why does ES6 classes could not be imported in typescript file? Is there some flag I should add to importing also js files and not only typescript .ts one? thx.

@Raminsiach
Copy link

With the newest version of angular2 I was able to make the bundle without including any script tags in my main html file. Changes that I made are as follow:
added this to my config.js:

  meta: {
    'npm:angular2@2.0.0-beta.9/*' : {
      deps: [
        'zone.js/dist/zone.js',
        'es6-shim'
      ]  
    } 
  }

and this in my bootstrap file:

import 'reflect-metadata';

my final main html file ended up as this:

<html>
<head>
    <title>Demo App</title>
    <base href="/">    
</head>
<body>
    <my-app>
        Loading...
    </my-app>
    <script src="main.sfx.js"></script>
</body>
</html>

@elimach
Copy link

elimach commented Mar 16, 2016

angular2@2.0.0-beta.9 depends on zone.js@0.5.15. But a install via jspm install angular2 zone.js installs also zone.js@0.6.4. Importing zone.js via import 'zone.js'; breaks Angular2-Change-Detection.

@davinkevin
Copy link

All seems to be ok for me today with JSPM 0.16.31 and

//package.json
"jspm": {
    "dependencies": {
      "angular2": "npm:angular2@^2.0.0-beta.11",
      "reflect-metadata": "npm:reflect-metadata@^0.1.3"
    },
    "devDependencies": {
      "typescript": "npm:typescript@^1.6.2"
    }
  }

and in the main.ts :

/**
 * Created by kevin on 05/03/2016.
 */
import 'reflect-metadata';
import 'angular2/bundles/angular2-polyfills';
import {bootstrap}    from 'angular2/platform/browser';
import {AppComponent} from './app.component.ts';

bootstrap(AppComponent);

All the code is in the following sandbox https://github.com/davinkevin/Angular2-Sandbox/tree/master/JSPM

@DavidGangel
Copy link

With Angular beta 11 it's not working due to:
angular/angular#7652

@Jefftopia
Copy link

@PhilippSoehnlein - can you describe your setup more?

I have

  meta: {
    'angular2/*': {
        deps: [
            'zone',
            'reflect-metadata'
        ]
    }
  },

  map: {
    "angular2": "npm:angular2@2.0.0-beta.12",
    "zone.js": "npm:zone.js@0.6.6",
...

and

error Error: XHR error (404 Not Found) loading http://localhost:2928/web/zone.js
    Error loading http://localhost:2928/web/zone.js as "zone" from http://localhost:2928/web/jspm_packages/npm/angular2@2.0.0-beta.12/platform/browser.js

In other words, it looks like System isn't using my map to locate zonejs.

@amcdnl
Copy link

amcdnl commented May 4, 2016

@robwormald - can u update for rc changes?

@crowmagnumb
Copy link

If I follow @rubyboy's procedure exactly, jspm installs 2.0.0-beta.17 and I get the following ...

system.js:4 Uncaught (in promise) Error: reflect-metadata shim is required when using class decorators

I have searched all over for solutions and none of them work. Anyone else try this with the latest? rc doesn't seem to be available yet on npm.

@playground
Copy link

playground commented May 7, 2016

@robwormald Just installed rc.1,

Error: Error: XHR error (404 Not Found) loading crypto.js
Error loading crypto.js as "crypto" from /jspm_packages/npm/reflect-metadata@0.1.3/Reflect.js

@LearnShare
Copy link

LearnShare commented May 9, 2016

@playground I got that error too, and I install crypto with jspm: jspm install crypto, then it works.

My package.json:

{
  "devDependencies": {
    "jspm": "^0.16.34"
  },
  "jspm": {
    "configFile": "jspm.config.js",
    "dependencies": {
      "@angular/core": "npm:@angular/core@^2.0.0-rc.1",
      "@angular/platform-browser-dynamic": "npm:@angular/platform-browser-dynamic@^2.0.0-rc.1",
      "@angular/router": "npm:@angular/router@^2.0.0-rc.1",
      "crypto": "github:jspm/nodelibs-crypto@^0.1.0",
      "css": "github:systemjs/plugin-css@^0.1.21",
      "less": "github:aaike/jspm-less-plugin@^0.0.5",
      "normalize.css": "github:necolas/normalize.css@^4.1.1",
      "reflect-metadata": "npm:reflect-metadata@^0.1.3",
      "rxjs": "npm:rxjs@^5.0.0-beta.7",
      "text": "github:systemjs/plugin-text@^0.0.8",
      "ts": "github:frankwallis/plugin-typescript@^4.0.9",
      "zone.js": "npm:zone.js@^0.6.12"
    },
    "devDependencies": {
      "typescript": "npm:typescript@^1.6.2"
    }
  }
}

I will try to make a https://github.com/angular/quickstart/ demo with jspm, it takes me almost a week to get it run.


https://github.com/LearnShare/angular-quickstart-jspm

Trying to make it auto-build-reload in jspm way.

@LearnShare
Copy link

@crowmagnumb
You need to load 'angular2/bundles/angular2-polyfills.js' with <script> tag.

But the npm:angular2 => npm:@angular/* since 2.0.0-rc.0 , and I can't find 'bundles/angular2-polyfills.js' anywhere.
Any one know that?

@randalvance
Copy link

Anyone used bundling with a component that has templateUrl? The bundled file can't seem to find the html templates.

@cdcooksey
Copy link

cdcooksey commented May 19, 2016

@LearnShare @crowmagnumb Angular2 release candidate removed angular2-polyfills.

It's replaced with this

import 'reflect-metadata';
require('zone.js/dist/zone');

@born2net
Copy link

born2net commented May 28, 2016

be awesome if we could get an example of using TypeScript 2.0 beta using directory mappings so we can get rid of node_modules as in: https://github.com/Microsoft/TypeScript-Handbook/blob/release-2.0/pages/Module%20Resolution.md#additional-module-resolution-flags

@vrghost242
Copy link

Got the following issue using jspm for angular2

system.src.js:1051 GET http://127.0.0.1:3000/jspm_packages/npm/angular2@2.0.0-beta.17/angular2.js 500 (Internal Server Error)

Looking at the config.js it reads:

System.config({
  baseURL: "/",
  defaultJSExtensions: true,
  transpiler: "typescript",
  paths: {
    "github:*": "jspm_packages/github/*",
    "npm:*": "jspm_packages/npm/*"
  },

  map: {
    "@angular/material": "npm:@angular/material@2.0.0-alpha.10",
    "angular2": "npm:angular2@2.0.0-beta.17/",
    "es6-shim": "github:es-shims/es6-shim@0.35.1",
    "reflect-metadata": "npm:reflect-metadata@0.1.8",
    "typescript": "npm:typescript@2.1.1",
    "zone.js": "npm:zone.js@0.6.26",
    "github:jspm/nodelibs-assert@0.1.0": {
      "assert": "npm:assert@1.4.1"
    },

And there is no angular2.js in the material@2.0.0-alpha.10 directory. There is one in the bundles directory under material@2.0.0-alpha.10.

In the directory there are the following files:

.jspm-hash
alt_router.d.ts
alt_router.js
alt_router.metadata.json
animate.d.ts
animate.js
common.d.ts
common.js
compiler.d.ts
compiler.js
core.d.ts
core.js
http.d.ts
http.js
http.metadata.json
i18n.d.ts
i18n.js
instrumentation.d.ts
instrumentation.js
LICENSE
package.json
README.md
router.d.ts
router.js
router.metadata.json
testing.d.ts
testing.js
testing_internal.d.ts
testing_internal.js
upgrade.d.ts
upgrade.js

Any idea what (most likely I did) wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment