Look ma, no build system!

JSPM/SystemJS + Angular 2

André Gaul

@andrenarchy


(CEO)

(activist)

Modules

CommonJS

// math.js exports.fibo = function fibo(n) { if (n <= 1) return n; return fibo(n - 1) + fibo(n - 2); }
var math = require('./math'); console.log(math.fibo(4)); // 3

ES2015

// math.js export function fibo(n) { if (n <= 1) return n; return fibo(n - 1) + fibo(n - 2); }
import { fibo } from './math'; console.log(fibo(4)); // 3

Modules

CommonJS

  • No browser support!
  • Used in NodeJS
  • Not part of JS standard
  • Bundling tools like browserify or webpack required
  • Build giant JS file with all dependencies

ES2015

  • No browser support (yet)!
  • Part of current JS standard (ES2015===ES6)
  • Browser support coming soon™
  • On-demand module loading with System.import()
  • Polyfill: SystemJS

Module system challenges

  • Resolve dependency tree
  • Locate external dependencies: what is this 'lodash' module in
    import { find } from 'lodash';
    ?
  • Multiple sources: npm, github (bower!), ${wtfpm}
  • Multiple module systems:
    • ES2015
    • CommonJS
    • AMD
    • no module system
      (global variables)
  • Multiple languages: transpile with TypeScript, Babel, ...

JSPM + SystemJS = <3

JSPM

  • Meta package manager
  • Supported out-of-the box: npm and github (bower!)
  • Flat dependencies
  • Provides package overrides
  • Generates SystemJS config

SystemJS

  • Reads generated config
  • Fetches module files from own server or CDN
  • Transpiles modules
  • Just works™

I want to see code. Now!

Example: ES2015

Get started

$ npm install -g jspm@beta $ jspm init # directories.lib: app # local package main: entry.js

Example: ES2015

index.html

<body> <script src="jspm_packages/system.js"></script> <script src="jspm.browser.js"></script> <script src="jspm.config.js"></script> <script> System.import('app') .catch(console.error.bind(console)); </script> </body>

Example: ES2015

app/entry.js

import { fibo } from './math'; console.log(fibo(4)); // 3

app/math.js

export function fibo(n) { if (n <= 1) return n; return fibo(n - 1) + fibo(n - 2); }

Example: ES2015

Install external module

$ jspm install lodash

app/entry.js

import { range } from 'lodash'; import { fibo } from './math'; const numbers = range(5).map(fibo); console.log(numbers); // [0, 1, 1, 2, 3]

Example: TypeScript + Angular2

Get started

$ npm install -g jspm@beta $ jspm init # directories.lib: app # local package main: entry.ts # transpiler: typescript $ jspm install angular2

Example: TypeScript + Angular2

tsconfig.json

{ "compilerOptions": { "target": "es6", "module": "system", "emitDecoratorMetadata": true, "experimentalDecorators": true, "noImplicitAny": false }, "exclude": [ "jspm_packages", "node_modules" ], "compileOnSave": false }

jspm.config.js

SystemJS.config({ transpiler: "plugin-typescript", typescriptOptions: { "tsconfig": true }, packages: { "app": { "main": "entry.ts", "defaultExtension": "ts", "meta": { "*.ts": { "loader": "plugin-typescript" } } } } });

Example: TypeScript + Angular2

index.html

<body> <main></main> <!-- add this! --> <script src="jspm_packages/system.js"></script> <script src="jspm.browser.js"></script> <script src="jspm.config.js"></script> <script> System.import('app') .catch(console.error.bind(console)); </script> </body>

Example: TypeScript + Angular2

app/main.ts

import { Component } from 'angular2/core'; @Component({ selector: 'main', template: '

Hey AngularJS meetup!

' }) export class MainComponent {};

Example: TypeScript + Angular2

app/entry.ts

import { bootstrap } from 'angular2/platform/browser'; import { MainComponent } from './main'; bootstrap(MainComponent);

Loading hundreds of small modules via HTTP takes forever!
Screw JSPM, I will continue to bundle a giant js file!

a concerned HTTP user

Solution: HTTP/2

  • Multiplexes multiple requests over single TCP connection
  • Major browsers support HTTP/2
  • Popular web servers support HTTP/2, e.g., nginx
  • But we still need an HTTP/2 dev server! Anyone?

Our JSPM experience

Development

  • Let the browser do the work
  • Live reloading works great with JSPM/SystemJS

Production

  • Let JSPM bundle the files before deployment:
    jspm build entry.ts bundle.js
  • Built-in optimizations (minify, rollup) may lead to broken code!
  • Alternative: dependency cache
    jspm depcache entry.ts

Rough edges of JSPM

  • Config is brittle (hey, it's beta!)
  • jspm install modifies jspm.{browser,config}.js and package.json
  • Keeping dependencies up-to-date requires manual interaction
    (tools like greenkeeper do not understand JSPM's config)
  • Community small but growing
  • Guy Bedford (JSPM+SystemJS dev) is super helpful if you run into trouble – Thanks for the awesome work, Guy!

Not covered here

  • Hot reloading: only reload modules that changed – while maintaining the app's state
  • TypeScript with ES2016 (ES7!): async/await!
  • Loading of assets (CSS, HTML, Jade, ...)

Thanks!

Questions?

PS: is hiring Angular devs! :D