ES2015 Stack
Using JSPM and JS library

ES2015 Modules
export function name1() {
};
export const name2 = 'value';
export let name3 = 1;
export class MyClass {};
let name4 = () => {};
let name5 = 5;
export { name4, name5 };
export { name4 as arrowFunc, name5 as five };
Named Exports
export default 'value';
Default Export
import theDefaultExport from 'lib';
import { name1, name2 } from 'lib';
import theDefaultExport, { name1 } from 'lib';
import { name1 as otherName } from 'lib';
import * as myLib from 'lib';
import 'lib';
Imports
Module Loader API
-
Dynamically declare and import modules
- Configure how modules are imported
Dynamic Imports
System.import('lib')
.then(myLib => {
// Code
})
.catch(error => {
// Error
});
Configure imports
System.config({
"map": {
"backbone": "npm:backbone@1.2.1",
"core-js": "npm:core-js@0.9.18",
"jquery": "github:components/jquery@1.11.3",
"underscore": "npm:underscore@1.8.3",
"github:jspm/nodelibs-http@1.7.1": {
"url": "github:jspm/nodelibs-url@0.1.0",
"util": "github:jspm/nodelibs-util@0.1.0"
},
"npm:core-js@0.9.18": {
"fs": "github:jspm/nodelibs-fs@0.1.2"
}
}
});
SystemJS
SystemJS is an
universal module manager
It can load:
define(['jquery'], function($) {
return function() {};
});
AMD Modules
var $ = require('jquery');
exports.myModule = function () {};
CommonJS Modules
var $ = require('jquery');
exports.myModule = function () {};
ES2015 Modules
window.myModule = function() {};
(Awful) Global Modules
You don't even CARE what kind of module you're loading!
With plugins, you can also load:
- CSS
- Text
- JSON
- Images
- Markdown
- JSX
- Fonts
- ...
Polyfill for the
ES2015 Module Loader
<script src="system.js"></script>
<script>
// loads relative to the current page URL
System.import('./local-module.js');
// load from an absolute URL directly
System.import('https://code.jquery.com/jquery.js');
</script>

Package manager
built on top of SystemJS
It can load packages
from any registry:
- NPM
- Bower
- Github
- JSPM
- ...
jspm install npm:aurelia
jspm install github:twbs/bootstrap
jspm install backbone
Generates SystemJS config automatically
Offers a CLI to bundle and unbundle our modules
(but we'll see that later...)

Front MVC framework with
4 kinds of elements

Template management is left to the developper
We're gonna use

Let's start
our project!
Setup NPM
and JSPM

npm init
# One global install for the CLI tools
npm install -g jspm
# One local install for the project
npm install --save-dev jspm
# Then we can init our jspm project
jspm init
# Add a prefix for jspm config into package.json. Let the default.
Would you like jspm to prefix the jspm package.json properties under jspm? [yes]:
# The default public folder path. Type "src".
Enter server baseURL (public folder path) [./]:src
# The folder in which our modules will be installed. Let the default.
Enter jspm packages folder [src/jspm_packages]:
# The systemJS config file path, let's type src/jspm-config.js.
Enter config file path [src/config.js]:src/jspm-config.js
# Let the default (yes).
Configuration file src/jspm-config.js doesn't exist, create it? [yes]:
# URL from the browser from where our website will be served. Let the default.
Enter client baseURL (public folder URL) [/]:
# We're going to use Babel. Let the default.
Which ES6 transpiler would you like to use, Traceur or Babel? [babel]:
JSPM Init:
the Questions
Our project is initialized!
Our application

A webpage that displays random quotes
jspm install backbone jquery
{
"quotes": [
{
"text": "I think the worst time to have a heart attack is during a game of charades.",
"author": "Demitri Martin"
}, {
"text": "When people ask me how many people work here, I say, about a third of them.",
"author": "Lisa Kennedy Montgomery"
}, {
"text": "Always and never are two words you should always remember never to use.",
"author": "Wendell Johnson"
}, {
"text": "Those who believe in telekinetics, raise my hand!",
"author": "Kurt Vonnegut"
}, {
"text": "Always go to other people's funerals, otherwise they won't come to yours.",
"author": "Yogi Berra"
}, {
"text": "Knowledge is knowing a tomato is a fruit; wisdom is not putting it in a fruit salad.",
"author": "Miles Kington"
}
]
}
src/config.json
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Random Quotes</title>
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.1.7/es5-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.1.7/es5-sham.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="view-main"></div>
<script src="/jspm_packages/system.js"></script>
<script src="/jspm-config.js"></script>
<script>
System['import']('../startup');
</script>
</body>
</html>
src/index.html
1- Load SystemJS
2- Load our SystemJS config
3- Import our entry point
(use ['import'] for IE8 compatibility)
import Backbone from 'backbone';
export default Backbone.Model.extend({
defaults: {
text: '',
author: ''
}
});
src/quote/QuoteModel.js
import Backbone from 'backbone';
import config from 'config.json!';
import Quote from 'quote/QuoteModel';
export default Backbone.Collection.extend({
model: Quote,
initialize() {
this.set(config.quotes);
}
});
src/quote/QuoteCollection.js
jspm install json
Load JSON config file
<blockquote class="quote">
{{ quote.text }}
<cite class="quote-author">{{ quote.author}}</cite>
</blockquote>
<button class="js-newQuote quoteButton">Another quote!</button>
src/quote/quoteTemplate.hbs
jspm install handlebars

html, body {
height: 100%;
}
body {
background-color: #daf0f8;
}
.view-main {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
}
.quote {
width: 60%;
margin: 0;
text-align: center;
font-family: Georgia, serif;
font-size: 3rem;
font-style: italic;
line-height: 1.45;
color: #383838;
}
@media (max-width: 1200px) {
.quote {
width: 90%;
}
}
.quote-author {
color: #999999;
font-size: 1.5rem;
display: block;
margin: 1rem 0;
text-align: center;
}
src/quote/quote.css
.quote-author:before, .quote-author:after {
content: "\2009 \2014 \2009";
}
.quoteButton {
position: relative;
margin-top: 2rem;
min-height: 3rem;
padding: 0.4rem 2rem;
border: 4px solid lightblue;
background: none;
border-radius: 20px;
font-size: 1.5rem;
font-family: Arial, serif;
font-style: italic;
}
.quoteButton:hover, .quoteButton:focus {
background-color: lightblue;
}
.quoteButton:active, .quoteButton:focus {
outline: none;
border: 4px solid lightblue;
}
.quoteButton:active:before, .quoteButton:focus:before {
content: ' ';
border-radius: 20px;
position: absolute;
border: 2px dashed white;
display: block;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
import Backbone from 'backbone';
import 'quote/quote.css!';
import renderTemplate from 'quote/quoteTemplate.hbs!';
import QuoteCollection from 'quote/QuoteCollection';
export default Backbone.View.extend({
el: '.view-main',
events: {
'click .js-newQuote': 'render'
},
initialize() {
this.quotes = new QuoteCollection();
},
render() {
let quote;
while((quote = this.quotes.sample()) && quote === this.quote);
this.quote = quote;
this.$el.html(renderTemplate({ quote: quote.toJSON() }));
}
});
src/quote/QuoteView.js
jspm install css
jspm install hbs=github:davis/plugin-hbs
1- Load CSS file
2- Load template
3- Select random quote
4- Render template
'quote/quote.css!css'
import Backbone from 'backbone';
import QuoteView from 'quote/QuoteView';
let AppRouter = Backbone.Router.extend({
routes: {
'': 'quote'
},
initialize() {
this.quoteView = new QuoteView();
},
quote() {
this.quoteView.render();
}
});
export default new AppRouter();
src/appRouters.js
import Backbone from 'backbone';
import 'appRouter';
Backbone.history.start();
startup.js
Let's industrialize our project!
Installation
Very easy, we only need to install npm and JSPM modules
{
"scripts": {
"postinstall": "jspm install"
}
}
npm install
package.json
Build
SystemJS is loading
many files
(= far too many requests)

jspm install npm:clean-css
Let's bundle them!
jspm bundle startup scripts.js --inject
-
Create a bundle file with startup and its dependencies
-
Store the result into scripts.js
- Inject the bundle configuration into our jspm-config.json
jspm bundle startup src/scripts.js --inject --minify
You can (and should)
even minify it
New bundle section
in our jspm-config.js
{
"bundles": {
"scripts": [
"npm:underscore@1.8.3/underscore",
"github:components/jquery@2.1.4/jquery",
"npm:process@0.10.1/browser",
"quote/quote.css!github:systemjs/plugin-css@0.1.13",
"github:components/handlebars.js@3.0.3/handlebars",
"config.json!github:systemjs/plugin-json@0.1.0",
"quote/QuoteModel",
"npm:underscore@1.8.3",
"github:components/jquery@2.1.4",
"npm:process@0.10.1",
"github:components/handlebars.js@3.0.3",
"quote/QuoteCollection",
"github:jspm/nodelibs-process@0.1.1/index",
"quote/quoteTemplate.hbs!github:davis/plugin-hbs@1.0.0",
"github:jspm/nodelibs-process@0.1.1",
"quote/QuoteView",
"npm:backbone@1.2.1/backbone",
"appRouter",
"npm:backbone@1.2.1",
"startup"
]
}
}
Result: 4 files loaded

But now it only loads the compiled file, how can I do when I'm coding?
jspm unbundle
(Remove all bundle config from the jspm-config.js file)
And if I want to load some files only when needed ?
=> Use System.import() and create several bundles !
jspm bundle "startup" src/global.js --inject --minify
jspm bundle "quote/* - startup" src/quotes.js --inject --minify
quote() {
let promise;
if(this.quoteView) {
promise = Promise.resolve(this.quoteView);
} else {
promise = System.import('quote/QuoteView').then(QuoteView => {
this.quoteView = new QuoteView['default']();
return this.quoteView;
});
}
return promise.then(quoteView => quoteView.render());
}
src/appRouter.js
Our build
- Bundle our scripts
- Clean dist directory
- Copy systemJS and index.html files
- Copy images files (even if there is none there)
- Move bundle files
- Unbundle our scripts
Gulp? Grunt? Broccoli?
Why not NPM ?
Our script
npm install -D rimraf cpy node-mv # Universal tools
jspm bundle startup src/modules/global.js --inject --minify
jspm bundle 'quote/**/* - startup' src/modules/quote.js --inject --minify
rimraf dist
cpy src/jspm_packages/*.* dist/jspm_packages
cpy src/index.html src/jspm-config.js dist
cpy **/*.png **/*.gif **/*.jpg ../dist --parents --cwd=src
cpy src/modules/**/* dist/modules
rimraf src/modules
jspm unbundle
src/scripts/build.js
(Don't forget to update the file chmod)
Our npm scripts
{
"scripts": {
"build": "./src/scripts/build.sh"
}
}
npm run build
package.json
Serve
What we want
-
Serve our files
- Auto-refresh our browser
2 in 1: browser-sync
browser-sync start --files 'src/**/*' --server 'src'
npm install --save-dev browser-sync
2 in 1: browser-sync
{
"scripts": {
"build": "sh ./src/scripts/build.sh",
"start": "jspm unbundle && browser-sync start --files 'src/**/*' --server 'src'"
}
}
npm start
package.json
Tests
ES2015 Stack with JSPM and Backbone
By Tarun Sharma
ES2015 Stack with JSPM and Backbone
- 1,140