Basics

Why it's crazy awesome

  • Supports every module format
  • Load dependencies from npm and bower
  • Build to bundles that optimize for caching and code reuse
  • Export your library to every format
  • Lots of plugins available; Less, Sass, QUnit, Jasmine, JSX, Conditionals, Cache Busting
  • Hot module swapping
  • Source maps

Core Projects

Module Loader

  • es6-module-loader
  • SystemJS
  • Steal
  • system-npm / system-bower
  • steal-css & steal-less
  • live-reload

Build Tools

  • StealTools
  • Transpile

Module Names

  • The key (or id) in a registry of modules (like a database)
  • Usually resolve to a file in your project (or a dependency)
    • Also could reflect modules dynamically created.
  • can/map/define/define
  • place-my-order/restaurant/list/list.stache!can/view/stache/system
    • place-my-order (package name)
    • restaurant/list/list.stache (module path)
    • stache
  • place-my-order/index.stache!done-autorender

Examples

Module Identifiers

define([
 "can",
 "./routes",
 "@loader",
 "form.stache!"
], function(){

});

app.js

Names used to identify modules in the context of another module.

Example

Current module:

Current address:

login

http://localhost/app/login/login.js

// login.js
define(["./form"], function(){

});

Importing:

./form

Normalized name:

form

Address:

http://localhost/app/form.js

Base Url:

http://localhost/app

Name-normalization

{
  "login": {
    "validation": {}, // -> "login/validation"
    "models": {
      "user": {}
    }
  },
  "form": {
    "submission": {}
  }
}
├── login/
|   ├── models/
|   |   ├── user.js
|   ├── login.js
|   ├── form.js
|   ├── validation.js

Better

login/login

login/form

Steal syntax

steal("login");

login/login

app

login/login

steal("./validation");

login/validation

steal("./form.js");

login/form

Configuration

System.configMain

  • stealconfig
    • config
    • my-config
  • package.json!npm
  • bower.json!bower

Forms

<script src="steal.js" data-config="config.js"></script>

<script src="node_modules/steal/steal.js"></script>

<script src="bower_components/steal/steal.js"></script>

<script src="node_modules/steal/steal.js" data-config="bower.json!bower"></script>

<script src="steal.js" config="package.json!npm"></script>

stealconfig.js

System.config({
    "paths": {
      "socket.io-client": "lib/packages/socket.io-client.js"
    },
    "meta": {
      "socket.io-client": {
        "format": "global"
      }
    },
    "ext": {
        "stache": "can/view/stache/system"
    }
});

package.json

{
    "name": "place-my-order",
    "version": "0.0.0",
    "system": {
        "map": {
          "socket.io-client": "socket.io-client/socket.io"
        },
        "meta": {
          "socket.io-client/socket.io": {
            "format": "global"
          }
        }
    }
}

Map

  • Changes a module name to another module name
  • Like an alias

Examples

lodash

System.config({
    map: {
        underscore: "lodash"
    }
});
{
    "name": "place-my-order",
    "version": "0.0.1",
    "system": {
        "map": {
            "socket.io-client": "socket.io-client/socket.io"
        }
    }
}

Socket.io

Paths

Specify the location of a module relative to the baseURL

CanJS

System.config({
    paths: {
        "jquery": "lib/jquery.js",
        "can": "lib/can/can.js",
        "can/*": "lib/can/*.js"
    }
});

Meta

Additional metadata about a module.

Mostly this is for globals

System.config({
    meta: {
        "jquery-datepicker": {
            exports: "jQuery",
            deps: ["jquery"]
        }
    }
});

Example

Ext

Like map, but applies to extensions.

Stache

System.config({
    ext: {
        stache: "can/view/stache/system"
    }
});
define([
    "./list.stache!"
], function(listTemplate){
  ...
});

stealconfig

restaurant/list

system-npm

An extension to load dependencies from node_modules

Crawling algorithm

https://github.com/stealjs/system-npm/blob/master/npm-crawl.js

├── node_modules/
|   ├── can
|   |   ├── package.json (deps: jquery)
|   |   ├── node_module/
|   ├── jquery
|   |   ├── package.json
|   ├── bit-tabs
|   |   ├── package.json (deps: can)
|   |   ├── node_modules/

package.json

{
    "name": "place-my-order",
    "version": "0.0.1",
    "dependencies": {
        "can": "^2.3.0-pre.8",
        "bit-tabs": "0.1.0-pre.1"
    },
    ...
}

place-my-order/

Module names

Needs

  • Module names must be distinct
  • Module names must be friendly
  • Multiple versions presents a problem
// app.js
define(["can"], function(can){

});

// system-npm
var normalize = System.normalize;
System.normalize = function(name, parentName){
    var pkg = npmUtils.getPackageByName(name, parentName);

    // pkg.name === "can"
    // pkg.main === "can.js",
    // pkg.version === "2.3.0-pre.7"

    return "can@2.3.0-pre.7#can";
};

Parts

can@2.3.0-pre.7#map/map

package name

package version

module path

{
    "name": "place-my-order",
    "version": "0.0.0",
    "system": {
        "meta": {
            "can/util/vdom/vdom": {
                "sideBundle": true
            }
        }
    }
}

Configuration

can@2.3.0-pre.7#util/vdom/vdom

Debugging Tricks

Stack traces

Not pretty, but useful

Who imported me?

<script src="node_modules/steal/steal.js"></script>
<script>
    var oldNormalize = System.normalize;
    System.normalize = function(name, parentName){
        return oldNormalize.apply(this, arguments).then(function(name){
            if(name === "my/module") {
                console.log(name, "is imported by", parentName);
            }
            return name;
        });
    };
</script>

https://gist.github.com/matthewp/1ce67c491fd3e6f18788

StealJS: High Level

By Matthew Phillips

StealJS: High Level

Everything you need to know to use and understand StealJS.

  • 809