Dependency management
&
Package management
in JavaScript
Sebastiano Armeli
@sebarmeli
WebExpo 2013, Prague (Czech Republic)
Friday, September 20, 13
Friday, September 20, 13
@sebarmeli
Sebastiano Armeli-Battana
• realestate.com.au
• Melbourne, Australia
Friday, September 20, 13
Dependency management
&
Package management
in JavaScript
Sebastiano Armeli
@sebarmeli
WebExpo 2013, Prague (Czech Republic)
Friday, September 20, 13
Dependency
management
Friday, September 20, 13
“A dependency
happens when a
component relies on
another one”
Friday, September 20, 13
View
<< depends on >>
Model
Friday, September 20, 13
model.js
------------
(function(window){
‘use strict’;
function Model() { }
window.Model = Model;
})(window);
Friday, September 20, 13
view.js
------------
(function(window){
‘use strict’;
function View(model) {
this.model = model;
}
window.View = View;
})(window);
Friday, September 20, 13
var model = new Model();
var view = new View(model);
Friday, September 20, 13
What to
consider when
you create
a dependency?
Friday, September 20, 13
Principles of
Package Coupling
Acyclic-Dependencies
Principle
Stable-Dependencies
Principle
Friday, September 20, 13
Stable
Dependencies
Principle
Friday, September 20, 13
Friday, September 20, 13
Unstable
Stable
View
Model
Friday, September 20, 13
Model DOES NOT change
frequently
View DOES change
frequently
Friday, September 20, 13
Acyclic
Dependencies
Principle
Friday, September 20, 13
Friday, September 20, 13
View
ModelRouter
Friday, September 20, 13
Avoid Cycles!
Friday, September 20, 13
How do we
handle
dependencies?
Friday, September 20, 13
Java
-----
import java.util.*;
import javax.servlet.http.*;
Ruby
-----
require ‘net/http’
require ‘spec_helper’
Friday, September 20, 13
...and in JS ?
Friday, September 20, 13
import jQuery from ‘jquery’;
Friday, September 20, 13
import jQuery from ‘jquery’;
ES6
Friday, September 20, 13
<script src=”file1.js”></script>
<script src=”file2.js”></script>
<script src=”file3.js”></script>
<script src=”file4.js”></script>
<script src=”file5.js”></script>
<script src=”file6.js”></script>
<script src=”file7.js”></script>
<script src=”file8.js”></script>
index.html
------------
Friday, September 20, 13
<script src=”file3.js”></script>
<script src=”file4.js”></script>
<script src=”file1.js”></script>
<script src=”file2.js”></script>
index.html
------------
<script src=”file5.js”></script>
<script src=”file6.js”></script>
<script src=”file7.js”></script>
<script src=”file8.js”></script>
Friday, September 20, 13
<script src=”file3.js”></script>
<script src=”file4.js”></script>
<script src=”file1.js”></script>
<script src=”file2.js”></script>
index.html
------------
<script src=”file5.js”></script>
<script src=”file6.js”></script>
<script src=”file7.js”></script>
<script src=”file8.js”></script>
Friday, September 20, 13
<script src=”file4.js”></script>
<script src=”file3.js”></script>
<script src=”file1.js”></script>
<script src=”file2.js”></script>
index.html
------------
<script src=”file5.js”></script>
<script src=”file6.js”></script>
<script src=”file7.js”></script>
<script src=”file8.js”></script>
Friday, September 20, 13
Friday, September 20, 13
Not only one
way to order
<script>s
Friday, September 20, 13
app.js view.js
helpers.jsview2.js
helpers2.js
model.js
Friday, September 20, 13
app.js view.js
helpers.jsview2.js
helpers2.js
model.js
1
2
3
5
4
6
Friday, September 20, 13
app.js view.js
helpers.jsview2.js
helpers2.js
model.js
1
2
3
5
4
6
4
1
3
2
5
6
Friday, September 20, 13
1
4
5
2
3
0 1
1 2,3
2 5
3 4
IN-DEGREES NODE
Friday, September 20, 13
4
5
2
3
0 2,3
2 5
3 4
IN-DEGREES NODE
1
Results:
Friday, September 20, 13
4
5
2
0 2
1 5
2 4
IN-DEGREES NODE
1 - 3
Results:
Friday, September 20, 13
4
5
0 5
1 4
IN-DEGREES NODE
1 - 3 - 2
Results:
Friday, September 20, 13
4
0 4
IN-DEGREES NODE
1 - 3 - 2 - 5
Results:
Friday, September 20, 13
1
4
5
2
3
1 - 3 - 2 - 5 - 4
4 - 5 - 2 - 3 - 1
Friday, September 20, 13
http://howardlewisship.com/images/t5-service-dependencies.jpg
Friday, September 20, 13
RequireJS
Friday, September 20, 13
Friday, September 20, 13
var module = (function(){
// private variables, methods
var title = “”;
function f1() {}
return {
// public/privileged methods
getTitle: function(){
return title;
}
}
}()) ;
MODULE PATTERN
Friday, September 20, 13
define(function () {
var title = “”;
function f1() {}
return {
getTitle: function() {
return title;
}
}
});
RJS MODULE PATTERN
Friday, September 20, 13
define(id?, dependencies?, factory)
Friday, September 20, 13
index.html
js /
-- main.js
-- helpers.js
-- app /
-- views /
-- view1.js
-- vendor /
-- require.js
view1.js
------------
define([‘helpers’],
function(helpers){
return {
init: function(){}
}
});
define(function(){
// code here
});
helpers.js
------------
Friday, September 20, 13
index.html
js /
-- main.js
-- helpers.js
-- app /
-- views /
-- view1.js
-- vendor /
-- require.js
view1.js
------------
define([‘helpers’],
function(helpers){
return {
init: function(){}
}
});
define(function(){
// code here
});
helpers.js
------------
Friday, September 20, 13
require(dependencies?, factory)
Friday, September 20, 13
index.html
------------
<script src=”js/vendor/require.js”
data-main=”js/main.js”></script>
main.js
------------
require([‘view1’],function(view1){
view1.init();
});
index.html
js /
-- main.js
-- helpers.js
-- app /
-- views /
-- view1.js
-- vendor /
-- require.js
Friday, September 20, 13
Friday, September 20, 13
main.js
------------
require.config({
baseUrl: ‘./js’,
paths: {
‘view1’: ‘app/views/view1’
}
});
require([‘view1’],function(view1){
view1.init();
});
index.html
js /
-- main.js
-- helpers.js
-- app /
-- views /
-- view1.js
-- vendor /
-- require.js
Friday, September 20, 13
NO blocking!
Friday, September 20, 13
require() asynchronous
de!ne() - de!ne.amd
AMD
well suited for browser
Friday, September 20, 13
Friday, September 20, 13
Friday, September 20, 13
if ( typeof define === "function" &&
define.amd ) {
define( "jquery", [], function () {
return jQuery;
});
}
Friday, September 20, 13
Friday, September 20, 13
index.html
js /
-- main.js
-- helpers.js
-- app /
-- views /
-- view1.js
-- vendor /
-- require.js
-- backbone.js
-- underscore.js
-- jquery.js
main.js
------------
require.config({
baseUrl: ‘js/vendor’,
shim: {
‘underscore’:{
exports: ‘_’
},
‘backbone’: {
deps: [‘jquery’, ‘underscore’],
exports: ‘Backbone’
}
}
});
require([‘backbone’],function(Backbone){
Backbone.history.start();
});
Friday, September 20, 13
index.html
js /
-- main.js
-- helpers.js
-- app /
-- views /
-- view1.js
-- vendor /
-- require.js
-- backbone.js
-- underscore.js
-- jquery.js
main.js
------------
require.config({
baseUrl: ‘js/vendor’,
shim: {
‘underscore’:{
exports: ‘_’
},
‘backbone’: {
deps: [‘jquery’, ‘underscore’],
exports: ‘Backbone’
}
}
});
require([‘backbone’],function(Backbone){
Backbone.history.start();
});
Friday, September 20, 13
LOADER PLUGINS
• i18n!, async!, domReady!
• text!, css!, json!, cs!, hbs!
[plugin Module ID]![resource ID]
Friday, September 20, 13
main.js
------------
require.config({
baseUrl: ‘./js’
});
require([‘text!partials/file.txt’],
function(txt) {
// txt goes here
});
index.html
js /
-- main.js
-- vendor /
-- require.js
-- text.js
-- partials /
-- !le.txt
Friday, September 20, 13
Friday, September 20, 13
3 requests!
Friday, September 20, 13
r.js
npm install -g requirejs
OPTIMIZER
Friday, September 20, 13
r.js -o tools/build.js
Friday, September 20, 13
build.js
------------
({
appDir:'../',
mainConfigFile: '../js/main.js',
dir: "../build",
modules: [
{
name: "../main"
}
]
})
index.html
js /
-- main.js
-- helpers.js
-- app /
-- views /
-- view1.js
-- vendor /
-- require.js
tools /
-- build.js
Friday, September 20, 13
build/js/main.js
----------------
index.html
build /
-- index.html
-- build.txt
-- js /
-- main.js
-- helpers.js
-- app /
-- views /
-- view1.js
-- vendor /
-- require.js
-- tools /
-- build.js
js/vendor/../main.js
----------------
js/helpers.js
js/vendor/view1.js
js/vendor/../main.js
build/build.txt
----------------
Friday, September 20, 13
OPTIMIZER
1 request!
Friday, September 20, 13
Friday, September 20, 13
exports.render = function() {};
var module = require(‘view1’);
NO de!ne()
require() synchronous
Server-side approach
Friday, September 20, 13
npm install -g browserify
Friday, September 20, 13
foo.js
------------
index.html
js /
-- main.js
-- foo.js
node_modules /
package.json
var Foo = function() {
// do something
};
module.exports = Foo;
main.js
------------
var Foo = require(‘./foo’);
var foo = new Foo();
Friday, September 20, 13
browserify js/main.js > js/bundle.js
Friday, September 20, 13
index.html
------------
index.html
js /
-- main.js
-- foo.js
-- bundle.js
node_modules /
package.json
bundle.js
------------;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o])
{var a=typeof require=="function"&&require;if(!u&&a)return
a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find
module '"+o+"'")}var f=n[o]={exports:{}};t[o]
[0].call(f.exports,function(e){var n=t[o][1][e];return
s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var
i=typeof require=="function"&&require;for(var
o=0;o<r.length;o++)s(r[o]);return s})({1:
[function(require,module,exports){
var Foo = function(){
console.log("AA");
};
module.exports = Foo;
},{}],2:[function(require,module,exports){
var Foo = require('./foo');
var foo = new Foo();
},{"./foo":1}]},{},[2])
<script src=”js/bundle.js”>
</script>
Friday, September 20, 13
Package
management
Friday, September 20, 13
Friday, September 20, 13
“A package is a
specific piece of
software installable”
Friday, September 20, 13
Packages
One or more modules
Friday, September 20, 13
Name, Description, Version
Metadata
Packages
One or more modules
Friday, September 20, 13
Name, Description, Version
Metadata
Packages
One or more modules
Checksum
Friday, September 20, 13
Name, Description, Version
Metadata
Packages
One or more modules
Checksum
Dependencies
Friday, September 20, 13
Package Manager
is the TOOL to...
Friday, September 20, 13
Speed up your development work"ow
Friday, September 20, 13
Speed up your development work"ow
Automate common tasks
Friday, September 20, 13
Speed up your development work"ow
Automate common tasks
DRY with Repository / Registry
Friday, September 20, 13
Common Operations
Friday, September 20, 13
Installing
Friday, September 20, 13
Installing
Removing
Friday, September 20, 13
Installing
Removing
Searching
Friday, September 20, 13
Installing
Removing
Searching
Upgrading
Friday, September 20, 13
Installing
Removing
Searching
Upgrading
Publishing
Friday, September 20, 13
Package Depedencies
A
B
C
C
Friday, September 20, 13
Package Depedencies
A
B
C
C
=1.1.0
>1.2.0
Friday, September 20, 13
Package Depedencies
A
B
C
C
=1.1.0
>1.2.0
Which version
should I
download?
Friday, September 20, 13
Java Ruby Python .Net OSX Linux
Maven/Gradle Rubygems pip NuGet Homebrew yum/apt
Friday, September 20, 13
How do you
install packages
in JS ?
Friday, September 20, 13
Friday, September 20, 13
Node.js
Friday, September 20, 13
package.json
Node.js
Friday, September 20, 13
package.json
NPM registry
Node.js
Friday, September 20, 13
package.json
------------
{
"name": "my-app",
"version": "0.0.1",
"dependencies": {
"jquery": "~2.0"
},
"devDependencies": {
"qunit": "0.5.x"
}
}
index.html
package.json
js /
-- app.js
Friday, September 20, 13
npm install
Friday, September 20, 13
npm install <package>
Commands
Friday, September 20, 13
npm install <package>
Commands
npm install -g <package>
Friday, September 20, 13
npm install <package>
Commands
npm install -g <package>
npm update <package>
Friday, September 20, 13
npm list
Commands
Friday, September 20, 13
npm list
Commands
npm uninstall <package>
Friday, September 20, 13
npm list
Commands
npm uninstall <package>
npm publish <tarball>
Friday, September 20, 13
is a not Package Manager
for the CLIENT
Friday, September 20, 13
Bower
Friday, September 20, 13
Bower
Minimalistic & Agnostic
Friday, September 20, 13
Bower
Minimalistic & Agnostic
HTML/CSS/JS
Friday, September 20, 13
Bower
Minimalistic & Agnostic
HTML/CSS/JS
AMD/CommonJS/ES6 modules
Friday, September 20, 13
npm install -g bower
Friday, September 20, 13
bower.json
------------
{
"name": "my-app",
"version": "0.0.1",
"ignore": [
"build",
"Gruntfile.js",
"package.json",
"bower.json"
],
"main": ["js/app.js"],
"dependencies": {
"requirejs": "~2.1.8", // >=2.1.8 < 2.2.0
"jquery": "~2.0" // >=2.0.0 < 2.1.0
},
"devDependencies": {
"qunit": "^1.12.0" // >=1.12.0 < 2.0.0
}
}
index.html
bower.json
js /
-- app.js
Friday, September 20, 13
bower install
Friday, September 20, 13
.bowerrc
------------
{
"directory”: “js/vendor”,
“json”: “bower.json”
}
index.html
bower.json
.bowerrc
js /
-- app.js
-- vendor/
-- jquery/
-- jquery.js
-- requirejs/
-- require.js
index.html
------------
<script src=”js/vendor/jquery/jquery.js >
</script>
Friday, September 20, 13
bower install jquery#1.8.2
Git tagAlias from registry
Friday, September 20, 13
bower install jquery --save
Friday, September 20, 13
bower install git://github.com/jquery/jquery.git#1.8.3
bower install ../my-package
Git endpoint + Git tag
Local package
bower install https://github.com/jquery/jquery.git
Git endpoint
Friday, September 20, 13
bower list
my-package
├── jquery#2.0.3
└── requirejs#2.1.8
Friday, September 20, 13
bower list
my-package
├── jquery#1.8.2 incompatible with ~2.0.0 (2.0.3 available)
└── requirejs#2.1.8
my-package
├── jquery#2.0.3
└── requirejs#2.1.8
Friday, September 20, 13
bower update jquery
bower uninstall jquery
bower info jquery
Friday, September 20, 13
bower register <package> <git_endpoint>
Friday, September 20, 13
Friday, September 20, 13
file1.js
-----------
require([‘module2’], function(){
// <use> <module2>;
});
Dependency management
Friday, September 20, 13
file1.js
-----------
var module2 = require(‘module2’);
// use module2
Dependency management
Friday, September 20, 13
source_file
-----------
<import> <module2>;
// <use> <module2>;
$ bower install jquery
Package management
Friday, September 20, 13
source_file
-----------
<import> <module2>;
// <use> <module2>;
$ npm install jquery
Package management
Friday, September 20, 13
http://requirejs.com
http://bower.io/
@sebarmeli
https://github.com/amdjs/amdjs-api/wiki/AMD
https://npmjs.org/
WebExpo 2013, Prague (Czech Republic)
Friday, September 20, 13

Dependency management & Package management in JavaScript