SlideShare a Scribd company logo
The Many Ways to Build
Modular JavaScript
Tim Perry
Tech Lead & Open-Source Champion at Softwire
@pimterry / github.com/pimterry / tim-perry.co.uk
JavaScript
 Originally designed by Brendan Eich for Netscape in mid-1995 as
LiveScript, based on his ideas from Scheme and Self, and implemented
over 10 days ‘or something worse than JS would have happened’.
 LiveScript ships in Netscape 2.0 that September
 Renamed to JavaScript three months later to confuse as many people as
possible for marketing purposes
 Standardisation begins a year later (now as ECMAScript), after everybody
has already implemented their own unique take.
 First ECMAScript spec is published in June 1997.
 16 years later, it’s the de facto standard language for all code on the
largest common platform in the world (and everybody still calls it
JavaScript)
JavaScript
Some great bits:
 Dynamic typing
 First-order functions & closures
Some features that just need removing:
 The ‘with’ keyword
 Much of type coercion
 Automatic semicolon insertion
Some fundamental structures that are hugely counter-intuitive:
 How ‘this’ and variable scope work
 Prototypes
Some clearly relevant features that don’t exist:
 Simple class definitions
 Tail-call optimizations
 A mechanism to allow structured modular code
Why?
coffeeFunctions.js:
function askAboutSugar() { … }
function askAboutMilk() { … }
function prepareMug(sugar, milk) { … }
function requestuserEmptyGrounds() { … }
function requestuserEmptyTray() { … }
function grindBeans() { … }
function putGroundsInFilter() { … }
function heatWater() { … }
function waterHotEnough() { … }
function pourCoffeeInMug () { … }
function serveMugToUser() { … }
index.html:
<html><body>
<button onclick=‚makeCoffee()‛>Make Coffee</button>
<script src=‚coffeeFunctions.js‛></script>
<script>
function makeCoffee() {
var sugars = askAboutSugar();
var milk = askAboutMilk();
prepareMug(sugars, milk);
while (!groundsAreEmpty) requestUserEmptyGrounds();
while (!dripTrayIsEmpty) requestUserEmptyTray();
grindBeans();
putGroundsInFilter();
heatWater();
while (!waterHotEnough()) wait();
pourCoffeeInMug();
serveMugToUser();
};
</script>
</body></html>
Why?
JavaScript uses lexically-defined function scoping
Variables definitions are either in local scope or global scope
function f() {
var localVar = ‚a string‛;
}
function f(localParameter) {
localParameter = ‚a string‛;
}
function f() {
function localFunction() {
}
}
var globalVar = ‚a string‛;
function g() {
globalVar = ‚a string‛;
}
function g() {
window.globalVar = ‚a string‛;
}
window.window.window.window === window;
Why?
index.html:
<html><body>
<button onclick=‚makeCoffee()‛>Make Coffee</button>
<script src=‚coffeeFunctions.js‛></script>
<script>
function makeCoffee() {
var sugars = askAboutSugar();
var milk = askAboutMilk();
prepareMug(sugars, milk);
while (!groundsAreEmpty) requestUserEmptyGrounds();
while (!dripTrayIsEmpty) requestUserEmptyTray();
grindBeans();
putGroundsInFilter();
heatWater();
while (!waterHotEnough()) wait();
pourCoffeeInMug();
serveMugToUser();
};
</script>
</body></html>
coffeeFunctions.js:
function askAboutSugar() { … }
function askAboutMilk() { … }
function prepareMug(sugar, milk) { … }
function requestuserEmptyGrounds() { … }
function requestuserEmptyTray() { … }
function grindBeans() { … }
function putGroundsInFilter() { … }
function heatWater() { … }
function waterHotEnough() { … }
function pourCoffeeInMug() { … }
function serveMugToUser() { … }
Why?
index.html:
<html><body>
<button onclick=‚makeCoffee()‛>Make Coffee</button>
<script src=‚coffeeFunctions.js‛></script>
<script>
function makeCoffee() {
var sugars = askAboutSugar();
var milk = askAboutMilk();
prepareMug(sugars, milk);
while (!groundsAreEmpty) requestUserEmptyGrounds();
while (!dripTrayIsEmpty) requestUserEmptyTray();
grindBeans();
putGroundsInFilter();
heatWater();
while (!waterHotEnough()) wait();
pourCoffeeInMug();
serveMugToUser();
};
</script>
</body></html>
coffeeFunctions.js:
function askAboutSugar() { … }
function askAboutMilk() { … }
function prepareMug(sugar, milk) { … }
function requestuserEmptyGrounds() { … }
function requestuserEmptyTray() { … }
function grindBeans() { … }
function putGroundsInFilter() { … }
function heatWater() { … }
function waterHotEnough() { … }
function pourCoffeeInMug() {
stopHeatingWater();
openCoffeeTap();
pourWaterThroughFilter();
}
function serveMugToUser() { … }
Why?
Global state makes systems
hard to reason about
Why?
Encapsulation breaks systems
into component parts, which
can be clearly reasoned about
index.html:
<html>
<body>
<button>Make Coffee</button>
<script src=‚beanGrinder.js‛></script>
<script src=‚hotWaterSource.js‛></script>
<script src=‚coffeeMachineUi.js‛></script>
<script src=‚coffeeController.js‛></script>
<script src=‚coffeeMachine.js‛></script>
<script>
coffeeMachine = new CoffeeMachine();
coffeeMachine.ui.show();
</script>
</body>
</html>
Why?
coffeeMachine.js:
function CoffeeMachine() {
var grinder = new BeanGrinder();
var hotWater = new HotWaterSource();
var ui = new CoffeeMachineUi();
var cc = new CoffeeController(grinder, hotWater, ui);
}
beanGrinder.js:
function BeanGrinder() { … }
coffeeController.js:
function CoffeeController(grinder, hotWater, ui) { … }
hotWaterSource.js:
function HotWaterSource() { … }
Why?
Build reusable chunks of code
Why?
beanGrinder.js:
function BeanGrinder() {
var beans = ko.observable(new BeanSupply());
var grindStrategy = new GrindStrategy();
this.grindBeans = function () { … };
}
coffeeMachineUi.js:
function CoffeeMachineUi() {
this.onMakeCoffee = function (makeCoffeeCallback) {
$(‚button‛).click(makeCoffeeCallback);
$(‚beanTypes‛).draggable();
};
this.askForSugar = function () { … };
this.askForMilk = function () { … };
this.confirmCancelMyCoffeePlease = function () { … };
}
hotWaterSource.js:
function HotWaterSource() {
var dynamicsCalculator = new FluidCalc();
this.openTap = function () { … }
this.startHeating = function () { … }
this.stopHeating = function () { … }
}
Why?
beanGrinder.js:
function BeanGrinder() {
var beans = ko.observable(new BeanSupply());
var grindStrategy = new GrindStrategy();
this.grindBeans = function () { … };
}
coffeeMachineUi.js:
function CoffeeMachineUi() {
this.onMakeCoffee = function (makeCoffeeCallback) {
$(‚button‛).click(makeCoffeeCallback);
$(‚beanTypes‛).draggable();
};
this.askForSugar = function () { … };
this.askForMilk = function () { … };
this.confirmCancelMyCoffeePlease = function () { … };
}
hotWaterSource.js:
function HotWaterSource() {
var dynamicsCalculator = new FluidCalc();
this.openTap = function () { … }
this.startHeating = function () { … }
this.stopHeating = function () { … }
}
index.html:
<html><body>
<script src=‚jquery.js‛></script>
<script src=‚jquery-ui.js‛></script>
<script src=‚knockout.js‛></script>
<script src=‚beanSupply.js‛></script>
<script src=‚grindStrategy.js‛></script>
<script src=‚fluidDynamicsLib.js‛></script>
<script src=‚beanGrinder.js‛></script>
<script src=‚coffeeMachineUi.js‛></script>
<script src=‚coffeeController.js‛></script>
<script src=‚hotWaterSource.js‛></script>
<script src=‚coffeeMachine.js‛></script>
<script>
coffeeMachine = new CoffeeMachine();
coffeeMachine.ui.show();
</script>
</body></html>
Why?
Why?
Be explicit about your
component’s external
dependencies
Why?
1. Encapsulated state
2. Reusable code
3. Explicit dependency management
Immediately-Invoked
Function Expression (IIFE)
window.coffeeMachine.moduleName = (function ($, grindStrategy) {
[… some code using these dependencies…]
return aModuleObject;
})(window.jQuery, window.coffeeMachine.grindStrategy);
Immediately-Invoked
Function Expression (IIFE)
window.coffeeMachine.moduleName = (function ($, grindStrategy) {
[… some code using these dependencies…]
return aModuleObject;
})(window.jQuery, window.coffeeMachine.grindStrategy);
Immediately-Invoked
Function Expression (IIFE)
window.coffeeMachine.moduleName = (function ($, grindStrategy) {
[… some code using these dependencies…]
return aModuleObject;
})(window.jQuery, window.coffeeMachine.grindStrategy);
Immediately-Invoked
Function Expression (IIFE)
window.coffeeMachine.moduleName = (function ($, grindStrategy) {
[… some code using these dependencies…]
return aModuleObject;
})(window.jQuery, window.coffeeMachine.grindStrategy);
Immediately-Invoked
Function Expression (IIFE)
window.coffeeMachine.moduleName = (function ($, grindStrategy) {
[… some code using these dependencies…]
return aModuleObject;
})(window.jQuery, window.coffeeMachine.grindStrategy);
IIFE Module Benefits
 Code internals are encapsulated
 Dependencies are explicitly named
 Code is reusable (in contexts where the dependencies are already
available)
IIFE Module Problems
 Global state has to be used to store each module exported from
an IIFE module
 Namespacing requires manual initialization and management
 Module loading and ordering still have to be managed manually
Asynchronous Module
Definitions (AMD)
define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛],
function ($, ko, coffeeGrinder) {
[… make coffee or build some private state or something …]
return {
‚doSomethingCoffeeRelated‛ : coffeeMakingFunction,
‚usefulNumber‛ : 4,
};
}
);
Asynchronous Module
Definitions (AMD)
define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛],
function ($, ko, coffeeGrinder) {
[… make coffee or build some private state or something …]
return {
‚doSomethingCoffeeRelated‛ : coffeeMakingFunction,
‚usefulNumber‛ : 4,
};
}
);
Asynchronous Module
Definitions (AMD)
define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛],
function ($, ko, coffeeGrinder) {
[… make coffee or build some private state or something …]
return {
‚doSomethingCoffeeRelated‛ : coffeeMakingFunction,
‚usefulNumber‛ : 4,
};
}
);
Asynchronous Module
Definitions (AMD)
define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛],
function ($, ko, coffeeGrinder) {
[… make coffee or build some private state or something …]
return {
‚doSomethingCoffeeRelated‛ : coffeeMakingFunction,
‚usefulNumber‛ : 4,
};
}
);
Asynchronous Module
Definitions (AMD)
define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛],
function ($, ko, coffeeGrinder) {
[… make coffee or build some private state or something …]
return {
‚doSomethingCoffeeRelated‛ : coffeeMakingFunction,
‚usefulNumber‛ : 4,
};
}
);
Asynchronous Module
Definitions (AMD)
require([‚font!fonts/myFavFont‛, ‚less!styles/homeStyle‛, ‚domReady!‛],
function () {
showPageNowThatAllPrerequisitesAreLoaded();
}
);
Asynchronous Module
Definitions (AMD)
require([‚font!fonts/myFavFont‛, ‚less!styles/homeStyle‛, ‚domReady!‛],
function () {
showPageNowThatAllPrerequisitesAreLoaded();
}
);
index.html:
<html>
<script src=‚require.js‛
data-main=‚scripts/main.js‛></script>
<body>
[ … ]
</body>
</html>
scripts/main.js
require([‚coffee/machine‛], function (CoffeeMachine) {
coffeeMachine = new CoffeeMachine();
coffeeMachine.ui.show();
});
Asynchronous Module
Definitions (AMD)
AMD Benefits
 Code internals are encapsulated, with explicitly exposed
interfaces
 Code is reusable as long as paths match or are aliased
 Dependencies are explicitly named
 Dependency loading is asynchronous, and can be done in
parallel
 Implemented in vanilla JavaScript only; no fundamental new
semantics
AMD Problems
 Lots of boilerplate (for JavaScript)
 Lots of complexity
 Can’t handle circular dependencies
 Can result in code that requires many HTTP requests to pull down its
large dependency network (solvable with R.js or similar)
CommonJS Modules
var $ = require(‚jquery‛);
var coffeeGrinder = require(‚./coffeeGrinder‛);
var niceBeans = require(‚./coffeeBeans‛).NICE_BEANS;
[… code to do something tenuously coffee related …]
exports.doSomethingCoffeeRelated = function () { … };
exports.usefulNumber = 4;
CommonJS Modules
var $ = require(‚jquery‛);
var coffeeGrinder = require(‚./coffeeGrinder‛);
var niceBeans = require(‚./coffeeBeans‛).NICE_BEANS;
[… code to do something tenuously coffee related …]
exports.doSomethingCoffeeRelated = function () { … };
exports.usefulNumber = 4;
CommonJS Modules
var $ = require(‚jquery‛);
var CoffeeGrinder = require(‚./coffeeGrinder‛).CoffeeGrinder;
var niceBeans = require(‚./coffeeBeans‛).NICE_BEANS;
[… code to do something tenuously coffee related …]
exports.doSomethingCoffeeRelated = function () { … };
exports.usefulNumber = 4;
CommonJS Runners
 Various non-browser platforms
 Browserify
 Require.js
CommonJS Runners
 Various non-browser platforms
 Node.JS, CouchDB, Narwhal, XULJet
 The native environment for CommonJS modules
 Synchronous loading makes perfect sense server-side
 Closer model to non-browser scripting languages
 Browserify
 Require.js
CommonJS Runners
 Various non-browser platforms
 Browserify
 CommonJS modules for the browser
 Build tool that takes CommonJS modules and compiles
the whole app into a single script file
 Lets node.js modules work directly in a browser
 Require.js
CommonJS Runners
 Various non-browser platforms
 Browserify
 Require.js
 Primarily an AMD script loader
 Can support CommonJS style modules, hackily, with:
define(function(require, exports) {
var beanTypes = require(‚coffeeMachine/beanTypes‛);
exports.favouriteBeanType = beanTypes[0];
});
CommonJS Benefits
 Code internals are encapsulated
 Dependencies are explicitly named
 Code is easily reusable
 Simple clean syntax and conceptual model
 Basically no boilerplate
 Handles circular references better than AMD
CommonJS Problems
 Lots of magic involved
 Doesn’t follow standard JavaScript conventions
 No consideration of environment where loads are expensive
 Ignores JavaScript’s inherent asynchronicity
 Dependencies aren’t necessarily all obvious upfront
ES6 Modules
module ‚aCoffeeComponent‛ {
import $ from ‘jquery’;
import { NICE_BEANS as niceBeans } from ‚beanTypes‛;
import ‘coffeeMachine/coffeeGrinder’ as grinder;
export default function doSomethingCoffeeRelated() { … };
export var usefulNumber = 4;
}
ES6 Modules
module ‚aCoffeeComponent‛ {
import $ from ‘jquery’;
import { NICE_BEANS as niceBeans } from ‚beanTypes‛;
import ‘coffeeMachine/coffeeGrinder’ as grinder;
export default function doSomethingCoffeeRelated() { … };
export var usefulNumber = 4;
}
ES6 Modules
module ‚aCoffeeComponent‛ {
import $ from ‘jquery’;
import { NICE_BEANS as niceBeans } from ‚beanTypes‛;
import ‘coffeeMachine/coffeeGrinder’ as grinder;
export default function doSomethingCoffeeRelated() { … };
export var usefulNumber = 4;
}
ES6 Modules
module ‚aCoffeeComponent‛ {
import $ from ‚jquery‛;
import { NICE_BEANS as niceBeans } from ‚beanTypes‛;
import ‘coffeeMachine/coffeeGrinder’ as grinder;
export default function doSomethingCoffeeRelated() { … };
export var usefulNumber = 4;
}
ES6 Module Benefits
 Likely to be extremely well supported everywhere, eventually
 More granular & powerful module import controls
 New syntax, but otherwise fairly true to existing JS semantics
 Fairly low on boilerplate
 Handles circular references even better
 Similar to other language concepts & syntax
 Modules can be declared either inline, or nested, or externally
ES6 Module Problems
 Currently supported effectively nowhere
 Not even final in the spec yet
 Quite a lot of genuinely new syntax
 import * is included, but is frowned upon in every other language
 Powerful, but thereby comparatively quite complicated
Which one do I use?
IIFE:
For tiny projects
For trivial
compatibility
AMD:
For most serious
browser-based
projects
For a no-build
pure-JS solution
If you need to
depend on non-JS
content/events
CommonJS:
For anything
outside a browser
environment
For anything in a
browser where
you might want
Node modules
ES6:
If you yearn for
the extremely
bleeding edge
And you live way
in the future
where it has real
support
Thank you
Tim Perry
Tech Lead & Open-Source Champion at Softwire
@pimterry / github.com/pimterry / tim-perry.co.uk

More Related Content

What's hot

Speed up your GWT coding with gQuery
Speed up your GWT coding with gQuerySpeed up your GWT coding with gQuery
Speed up your GWT coding with gQuery
Manuel Carrasco Moñino
 
AngularJs
AngularJsAngularJs
AngularJs
syam kumar kk
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgets
scottw
 
Redux vs Alt
Redux vs AltRedux vs Alt
Redux vs Alt
Uldis Sturms
 
[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법
Jeado Ko
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of today
gerbille
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
Bert Wijnants
 
GQuery a jQuery clone for Gwt, RivieraDev 2011
GQuery a jQuery clone for Gwt, RivieraDev 2011GQuery a jQuery clone for Gwt, RivieraDev 2011
GQuery a jQuery clone for Gwt, RivieraDev 2011
Manuel Carrasco Moñino
 
React, Redux and es6/7
React, Redux and es6/7React, Redux and es6/7
React, Redux and es6/7
Dongho Cho
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
Visual Engineering
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Jeado Ko
 
Backbone js
Backbone jsBackbone js
Backbone js
rstankov
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0
Jeado Ko
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
rstankov
 
Workshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte IIIWorkshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte III
Visual Engineering
 
Why ruby
Why rubyWhy ruby
Why ruby
rstankov
 
AngularJS Basics with Example
AngularJS Basics with ExampleAngularJS Basics with Example
AngularJS Basics with Example
Sergey Bolshchikov
 
Arquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com JetpackArquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com Jetpack
Nelson Glauber Leal
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
toddbr
 
Web components
Web componentsWeb components
Web components
Tudor Barbu
 

What's hot (20)

Speed up your GWT coding with gQuery
Speed up your GWT coding with gQuerySpeed up your GWT coding with gQuery
Speed up your GWT coding with gQuery
 
AngularJs
AngularJsAngularJs
AngularJs
 
Build Widgets
Build WidgetsBuild Widgets
Build Widgets
 
Redux vs Alt
Redux vs AltRedux vs Alt
Redux vs Alt
 
[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of today
 
Viking academy backbone.js
Viking academy  backbone.jsViking academy  backbone.js
Viking academy backbone.js
 
GQuery a jQuery clone for Gwt, RivieraDev 2011
GQuery a jQuery clone for Gwt, RivieraDev 2011GQuery a jQuery clone for Gwt, RivieraDev 2011
GQuery a jQuery clone for Gwt, RivieraDev 2011
 
React, Redux and es6/7
React, Redux and es6/7React, Redux and es6/7
React, Redux and es6/7
 
Workshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte IWorkshop 12: AngularJS Parte I
Workshop 12: AngularJS Parte I
 
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
 
Backbone js
Backbone jsBackbone js
Backbone js
 
준비하세요 Angular js 2.0
준비하세요 Angular js 2.0준비하세요 Angular js 2.0
준비하세요 Angular js 2.0
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Workshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte IIIWorkshop 14: AngularJS Parte III
Workshop 14: AngularJS Parte III
 
Why ruby
Why rubyWhy ruby
Why ruby
 
AngularJS Basics with Example
AngularJS Basics with ExampleAngularJS Basics with Example
AngularJS Basics with Example
 
Arquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com JetpackArquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com Jetpack
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
Web components
Web componentsWeb components
Web components
 

Similar to The Many Ways to Build Modular JavaScript

ASP.NET MVC Internals
ASP.NET MVC InternalsASP.NET MVC Internals
ASP.NET MVC Internals
Vitaly Baum
 
Dancing with websocket
Dancing with websocketDancing with websocket
Dancing with websocket
Damien Krotkine
 
Vaadin 7 CN
Vaadin 7 CNVaadin 7 CN
Vaadin 7 CN
jojule
 
Mozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJSMozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJS
Robert Nyman
 
Building Isomorphic Apps (JSConf.Asia 2014)
Building Isomorphic Apps (JSConf.Asia 2014)Building Isomorphic Apps (JSConf.Asia 2014)
Building Isomorphic Apps (JSConf.Asia 2014)
Spike Brehm
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
Fabio Franzini
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
dion
 
Wt unit 5
Wt unit 5Wt unit 5
Wt unit 5
team11vgnt
 
Javascript frameworks: Backbone.js
Javascript frameworks: Backbone.jsJavascript frameworks: Backbone.js
Javascript frameworks: Backbone.js
Soós Gábor
 
ParisJS #10 : RequireJS
ParisJS #10 : RequireJSParisJS #10 : RequireJS
ParisJS #10 : RequireJS
Julien Cabanès
 
using Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API'susing Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API's
Antônio Roberto Silva
 
jQuery
jQueryjQuery
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
Skills Matter
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
Skills Matter
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Paulo Ragonha
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
Mike Subelsky
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Pattern
goodfriday
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
Domenic Denicola
 
HTML5: huh, what is it good for?
HTML5: huh, what is it good for?HTML5: huh, what is it good for?
HTML5: huh, what is it good for?
Remy Sharp
 
Meetup Performance
Meetup PerformanceMeetup Performance
Meetup Performance
Greg Whalin
 

Similar to The Many Ways to Build Modular JavaScript (20)

ASP.NET MVC Internals
ASP.NET MVC InternalsASP.NET MVC Internals
ASP.NET MVC Internals
 
Dancing with websocket
Dancing with websocketDancing with websocket
Dancing with websocket
 
Vaadin 7 CN
Vaadin 7 CNVaadin 7 CN
Vaadin 7 CN
 
Mozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJSMozilla Web Apps - Super-VanJS
Mozilla Web Apps - Super-VanJS
 
Building Isomorphic Apps (JSConf.Asia 2014)
Building Isomorphic Apps (JSConf.Asia 2014)Building Isomorphic Apps (JSConf.Asia 2014)
Building Isomorphic Apps (JSConf.Asia 2014)
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
Wt unit 5
Wt unit 5Wt unit 5
Wt unit 5
 
Javascript frameworks: Backbone.js
Javascript frameworks: Backbone.jsJavascript frameworks: Backbone.js
Javascript frameworks: Backbone.js
 
ParisJS #10 : RequireJS
ParisJS #10 : RequireJSParisJS #10 : RequireJS
ParisJS #10 : RequireJS
 
using Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API'susing Mithril.js + postgREST to build and consume API's
using Mithril.js + postgREST to build and consume API's
 
jQuery
jQueryjQuery
jQuery
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
 
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and JasmineSingle Page Web Applications with CoffeeScript, Backbone and Jasmine
Single Page Web Applications with CoffeeScript, Backbone and Jasmine
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Developing ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller PatternDeveloping ASP.NET Applications Using the Model View Controller Pattern
Developing ASP.NET Applications Using the Model View Controller Pattern
 
JavaScript on the Desktop
JavaScript on the DesktopJavaScript on the Desktop
JavaScript on the Desktop
 
HTML5: huh, what is it good for?
HTML5: huh, what is it good for?HTML5: huh, what is it good for?
HTML5: huh, what is it good for?
 
Meetup Performance
Meetup PerformanceMeetup Performance
Meetup Performance
 

Recently uploaded

Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
Brandon Minnick, MBA
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Jeffrey Haguewood
 
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - HiikeSystem Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
Hiike
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
panagenda
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Alpen-Adria-Universität
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
Zilliz
 
Trusted Execution Environment for Decentralized Process Mining
Trusted Execution Environment for Decentralized Process MiningTrusted Execution Environment for Decentralized Process Mining
Trusted Execution Environment for Decentralized Process Mining
LucaBarbaro3
 
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStrDeep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
saastr
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
shyamraj55
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
SitimaJohn
 
UI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentationUI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentation
Wouter Lemaire
 
leewayhertz.com-AI in predictive maintenance Use cases technologies benefits ...
leewayhertz.com-AI in predictive maintenance Use cases technologies benefits ...leewayhertz.com-AI in predictive maintenance Use cases technologies benefits ...
leewayhertz.com-AI in predictive maintenance Use cases technologies benefits ...
alexjohnson7307
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
innovationoecd
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
MichaelKnudsen27
 
Operating System Used by Users in day-to-day life.pptx
Operating System Used by Users in day-to-day life.pptxOperating System Used by Users in day-to-day life.pptx
Operating System Used by Users in day-to-day life.pptx
Pravash Chandra Das
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
Octavian Nadolu
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
Zilliz
 
Azure API Management to expose backend services securely
Azure API Management to expose backend services securelyAzure API Management to expose backend services securely
Azure API Management to expose backend services securely
Dinusha Kumarasiri
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Safe Software
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
Pixlogix Infotech
 

Recently uploaded (20)

Choosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptxChoosing The Best AWS Service For Your Website + API.pptx
Choosing The Best AWS Service For Your Website + API.pptx
 
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
Salesforce Integration for Bonterra Impact Management (fka Social Solutions A...
 
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - HiikeSystem Design Case Study: Building a Scalable E-Commerce Platform - Hiike
System Design Case Study: Building a Scalable E-Commerce Platform - Hiike
 
HCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAUHCL Notes and Domino License Cost Reduction in the World of DLAU
HCL Notes and Domino License Cost Reduction in the World of DLAU
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
 
Trusted Execution Environment for Decentralized Process Mining
Trusted Execution Environment for Decentralized Process MiningTrusted Execution Environment for Decentralized Process Mining
Trusted Execution Environment for Decentralized Process Mining
 
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStrDeep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
Deep Dive: Getting Funded with Jason Jason Lemkin Founder & CEO @ SaaStr
 
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with SlackLet's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
Let's Integrate MuleSoft RPA, COMPOSER, APM with AWS IDP along with Slack
 
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptxOcean lotus Threat actors project by John Sitima 2024 (1).pptx
Ocean lotus Threat actors project by John Sitima 2024 (1).pptx
 
UI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentationUI5 Controls simplified - UI5con2024 presentation
UI5 Controls simplified - UI5con2024 presentation
 
leewayhertz.com-AI in predictive maintenance Use cases technologies benefits ...
leewayhertz.com-AI in predictive maintenance Use cases technologies benefits ...leewayhertz.com-AI in predictive maintenance Use cases technologies benefits ...
leewayhertz.com-AI in predictive maintenance Use cases technologies benefits ...
 
Presentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of GermanyPresentation of the OECD Artificial Intelligence Review of Germany
Presentation of the OECD Artificial Intelligence Review of Germany
 
Nordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptxNordic Marketo Engage User Group_June 13_ 2024.pptx
Nordic Marketo Engage User Group_June 13_ 2024.pptx
 
Operating System Used by Users in day-to-day life.pptx
Operating System Used by Users in day-to-day life.pptxOperating System Used by Users in day-to-day life.pptx
Operating System Used by Users in day-to-day life.pptx
 
Artificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopmentArtificial Intelligence for XMLDevelopment
Artificial Intelligence for XMLDevelopment
 
Building Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and MilvusBuilding Production Ready Search Pipelines with Spark and Milvus
Building Production Ready Search Pipelines with Spark and Milvus
 
Azure API Management to expose backend services securely
Azure API Management to expose backend services securelyAzure API Management to expose backend services securely
Azure API Management to expose backend services securely
 
Driving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success StoryDriving Business Innovation: Latest Generative AI Advancements & Success Story
Driving Business Innovation: Latest Generative AI Advancements & Success Story
 
Best 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERPBest 20 SEO Techniques To Improve Website Visibility In SERP
Best 20 SEO Techniques To Improve Website Visibility In SERP
 

The Many Ways to Build Modular JavaScript

  • 1. The Many Ways to Build Modular JavaScript Tim Perry Tech Lead & Open-Source Champion at Softwire @pimterry / github.com/pimterry / tim-perry.co.uk
  • 2. JavaScript  Originally designed by Brendan Eich for Netscape in mid-1995 as LiveScript, based on his ideas from Scheme and Self, and implemented over 10 days ‘or something worse than JS would have happened’.  LiveScript ships in Netscape 2.0 that September  Renamed to JavaScript three months later to confuse as many people as possible for marketing purposes  Standardisation begins a year later (now as ECMAScript), after everybody has already implemented their own unique take.  First ECMAScript spec is published in June 1997.  16 years later, it’s the de facto standard language for all code on the largest common platform in the world (and everybody still calls it JavaScript)
  • 3.
  • 4. JavaScript Some great bits:  Dynamic typing  First-order functions & closures Some features that just need removing:  The ‘with’ keyword  Much of type coercion  Automatic semicolon insertion Some fundamental structures that are hugely counter-intuitive:  How ‘this’ and variable scope work  Prototypes Some clearly relevant features that don’t exist:  Simple class definitions  Tail-call optimizations  A mechanism to allow structured modular code
  • 5. Why? coffeeFunctions.js: function askAboutSugar() { … } function askAboutMilk() { … } function prepareMug(sugar, milk) { … } function requestuserEmptyGrounds() { … } function requestuserEmptyTray() { … } function grindBeans() { … } function putGroundsInFilter() { … } function heatWater() { … } function waterHotEnough() { … } function pourCoffeeInMug () { … } function serveMugToUser() { … } index.html: <html><body> <button onclick=‚makeCoffee()‛>Make Coffee</button> <script src=‚coffeeFunctions.js‛></script> <script> function makeCoffee() { var sugars = askAboutSugar(); var milk = askAboutMilk(); prepareMug(sugars, milk); while (!groundsAreEmpty) requestUserEmptyGrounds(); while (!dripTrayIsEmpty) requestUserEmptyTray(); grindBeans(); putGroundsInFilter(); heatWater(); while (!waterHotEnough()) wait(); pourCoffeeInMug(); serveMugToUser(); }; </script> </body></html>
  • 6. Why? JavaScript uses lexically-defined function scoping Variables definitions are either in local scope or global scope function f() { var localVar = ‚a string‛; } function f(localParameter) { localParameter = ‚a string‛; } function f() { function localFunction() { } } var globalVar = ‚a string‛; function g() { globalVar = ‚a string‛; } function g() { window.globalVar = ‚a string‛; } window.window.window.window === window;
  • 7. Why? index.html: <html><body> <button onclick=‚makeCoffee()‛>Make Coffee</button> <script src=‚coffeeFunctions.js‛></script> <script> function makeCoffee() { var sugars = askAboutSugar(); var milk = askAboutMilk(); prepareMug(sugars, milk); while (!groundsAreEmpty) requestUserEmptyGrounds(); while (!dripTrayIsEmpty) requestUserEmptyTray(); grindBeans(); putGroundsInFilter(); heatWater(); while (!waterHotEnough()) wait(); pourCoffeeInMug(); serveMugToUser(); }; </script> </body></html> coffeeFunctions.js: function askAboutSugar() { … } function askAboutMilk() { … } function prepareMug(sugar, milk) { … } function requestuserEmptyGrounds() { … } function requestuserEmptyTray() { … } function grindBeans() { … } function putGroundsInFilter() { … } function heatWater() { … } function waterHotEnough() { … } function pourCoffeeInMug() { … } function serveMugToUser() { … }
  • 8. Why? index.html: <html><body> <button onclick=‚makeCoffee()‛>Make Coffee</button> <script src=‚coffeeFunctions.js‛></script> <script> function makeCoffee() { var sugars = askAboutSugar(); var milk = askAboutMilk(); prepareMug(sugars, milk); while (!groundsAreEmpty) requestUserEmptyGrounds(); while (!dripTrayIsEmpty) requestUserEmptyTray(); grindBeans(); putGroundsInFilter(); heatWater(); while (!waterHotEnough()) wait(); pourCoffeeInMug(); serveMugToUser(); }; </script> </body></html> coffeeFunctions.js: function askAboutSugar() { … } function askAboutMilk() { … } function prepareMug(sugar, milk) { … } function requestuserEmptyGrounds() { … } function requestuserEmptyTray() { … } function grindBeans() { … } function putGroundsInFilter() { … } function heatWater() { … } function waterHotEnough() { … } function pourCoffeeInMug() { stopHeatingWater(); openCoffeeTap(); pourWaterThroughFilter(); } function serveMugToUser() { … }
  • 9. Why? Global state makes systems hard to reason about
  • 10. Why? Encapsulation breaks systems into component parts, which can be clearly reasoned about
  • 11. index.html: <html> <body> <button>Make Coffee</button> <script src=‚beanGrinder.js‛></script> <script src=‚hotWaterSource.js‛></script> <script src=‚coffeeMachineUi.js‛></script> <script src=‚coffeeController.js‛></script> <script src=‚coffeeMachine.js‛></script> <script> coffeeMachine = new CoffeeMachine(); coffeeMachine.ui.show(); </script> </body> </html> Why? coffeeMachine.js: function CoffeeMachine() { var grinder = new BeanGrinder(); var hotWater = new HotWaterSource(); var ui = new CoffeeMachineUi(); var cc = new CoffeeController(grinder, hotWater, ui); } beanGrinder.js: function BeanGrinder() { … } coffeeController.js: function CoffeeController(grinder, hotWater, ui) { … } hotWaterSource.js: function HotWaterSource() { … }
  • 13. Why? beanGrinder.js: function BeanGrinder() { var beans = ko.observable(new BeanSupply()); var grindStrategy = new GrindStrategy(); this.grindBeans = function () { … }; } coffeeMachineUi.js: function CoffeeMachineUi() { this.onMakeCoffee = function (makeCoffeeCallback) { $(‚button‛).click(makeCoffeeCallback); $(‚beanTypes‛).draggable(); }; this.askForSugar = function () { … }; this.askForMilk = function () { … }; this.confirmCancelMyCoffeePlease = function () { … }; } hotWaterSource.js: function HotWaterSource() { var dynamicsCalculator = new FluidCalc(); this.openTap = function () { … } this.startHeating = function () { … } this.stopHeating = function () { … } }
  • 14. Why? beanGrinder.js: function BeanGrinder() { var beans = ko.observable(new BeanSupply()); var grindStrategy = new GrindStrategy(); this.grindBeans = function () { … }; } coffeeMachineUi.js: function CoffeeMachineUi() { this.onMakeCoffee = function (makeCoffeeCallback) { $(‚button‛).click(makeCoffeeCallback); $(‚beanTypes‛).draggable(); }; this.askForSugar = function () { … }; this.askForMilk = function () { … }; this.confirmCancelMyCoffeePlease = function () { … }; } hotWaterSource.js: function HotWaterSource() { var dynamicsCalculator = new FluidCalc(); this.openTap = function () { … } this.startHeating = function () { … } this.stopHeating = function () { … } }
  • 15. index.html: <html><body> <script src=‚jquery.js‛></script> <script src=‚jquery-ui.js‛></script> <script src=‚knockout.js‛></script> <script src=‚beanSupply.js‛></script> <script src=‚grindStrategy.js‛></script> <script src=‚fluidDynamicsLib.js‛></script> <script src=‚beanGrinder.js‛></script> <script src=‚coffeeMachineUi.js‛></script> <script src=‚coffeeController.js‛></script> <script src=‚hotWaterSource.js‛></script> <script src=‚coffeeMachine.js‛></script> <script> coffeeMachine = new CoffeeMachine(); coffeeMachine.ui.show(); </script> </body></html> Why?
  • 16. Why? Be explicit about your component’s external dependencies
  • 17. Why? 1. Encapsulated state 2. Reusable code 3. Explicit dependency management
  • 18. Immediately-Invoked Function Expression (IIFE) window.coffeeMachine.moduleName = (function ($, grindStrategy) { [… some code using these dependencies…] return aModuleObject; })(window.jQuery, window.coffeeMachine.grindStrategy);
  • 19. Immediately-Invoked Function Expression (IIFE) window.coffeeMachine.moduleName = (function ($, grindStrategy) { [… some code using these dependencies…] return aModuleObject; })(window.jQuery, window.coffeeMachine.grindStrategy);
  • 20. Immediately-Invoked Function Expression (IIFE) window.coffeeMachine.moduleName = (function ($, grindStrategy) { [… some code using these dependencies…] return aModuleObject; })(window.jQuery, window.coffeeMachine.grindStrategy);
  • 21. Immediately-Invoked Function Expression (IIFE) window.coffeeMachine.moduleName = (function ($, grindStrategy) { [… some code using these dependencies…] return aModuleObject; })(window.jQuery, window.coffeeMachine.grindStrategy);
  • 22. Immediately-Invoked Function Expression (IIFE) window.coffeeMachine.moduleName = (function ($, grindStrategy) { [… some code using these dependencies…] return aModuleObject; })(window.jQuery, window.coffeeMachine.grindStrategy);
  • 23. IIFE Module Benefits  Code internals are encapsulated  Dependencies are explicitly named  Code is reusable (in contexts where the dependencies are already available)
  • 24. IIFE Module Problems  Global state has to be used to store each module exported from an IIFE module  Namespacing requires manual initialization and management  Module loading and ordering still have to be managed manually
  • 25. Asynchronous Module Definitions (AMD) define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛], function ($, ko, coffeeGrinder) { [… make coffee or build some private state or something …] return { ‚doSomethingCoffeeRelated‛ : coffeeMakingFunction, ‚usefulNumber‛ : 4, }; } );
  • 26. Asynchronous Module Definitions (AMD) define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛], function ($, ko, coffeeGrinder) { [… make coffee or build some private state or something …] return { ‚doSomethingCoffeeRelated‛ : coffeeMakingFunction, ‚usefulNumber‛ : 4, }; } );
  • 27. Asynchronous Module Definitions (AMD) define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛], function ($, ko, coffeeGrinder) { [… make coffee or build some private state or something …] return { ‚doSomethingCoffeeRelated‛ : coffeeMakingFunction, ‚usefulNumber‛ : 4, }; } );
  • 28. Asynchronous Module Definitions (AMD) define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛], function ($, ko, coffeeGrinder) { [… make coffee or build some private state or something …] return { ‚doSomethingCoffeeRelated‛ : coffeeMakingFunction, ‚usefulNumber‛ : 4, }; } );
  • 29. Asynchronous Module Definitions (AMD) define([‚lib/jquery‛, ‚lib/knockout‛, ‚coffeeMachine/grinder‛], function ($, ko, coffeeGrinder) { [… make coffee or build some private state or something …] return { ‚doSomethingCoffeeRelated‛ : coffeeMakingFunction, ‚usefulNumber‛ : 4, }; } );
  • 30. Asynchronous Module Definitions (AMD) require([‚font!fonts/myFavFont‛, ‚less!styles/homeStyle‛, ‚domReady!‛], function () { showPageNowThatAllPrerequisitesAreLoaded(); } );
  • 31. Asynchronous Module Definitions (AMD) require([‚font!fonts/myFavFont‛, ‚less!styles/homeStyle‛, ‚domReady!‛], function () { showPageNowThatAllPrerequisitesAreLoaded(); } );
  • 32. index.html: <html> <script src=‚require.js‛ data-main=‚scripts/main.js‛></script> <body> [ … ] </body> </html> scripts/main.js require([‚coffee/machine‛], function (CoffeeMachine) { coffeeMachine = new CoffeeMachine(); coffeeMachine.ui.show(); }); Asynchronous Module Definitions (AMD)
  • 33. AMD Benefits  Code internals are encapsulated, with explicitly exposed interfaces  Code is reusable as long as paths match or are aliased  Dependencies are explicitly named  Dependency loading is asynchronous, and can be done in parallel  Implemented in vanilla JavaScript only; no fundamental new semantics
  • 34. AMD Problems  Lots of boilerplate (for JavaScript)  Lots of complexity  Can’t handle circular dependencies  Can result in code that requires many HTTP requests to pull down its large dependency network (solvable with R.js or similar)
  • 35. CommonJS Modules var $ = require(‚jquery‛); var coffeeGrinder = require(‚./coffeeGrinder‛); var niceBeans = require(‚./coffeeBeans‛).NICE_BEANS; [… code to do something tenuously coffee related …] exports.doSomethingCoffeeRelated = function () { … }; exports.usefulNumber = 4;
  • 36. CommonJS Modules var $ = require(‚jquery‛); var coffeeGrinder = require(‚./coffeeGrinder‛); var niceBeans = require(‚./coffeeBeans‛).NICE_BEANS; [… code to do something tenuously coffee related …] exports.doSomethingCoffeeRelated = function () { … }; exports.usefulNumber = 4;
  • 37. CommonJS Modules var $ = require(‚jquery‛); var CoffeeGrinder = require(‚./coffeeGrinder‛).CoffeeGrinder; var niceBeans = require(‚./coffeeBeans‛).NICE_BEANS; [… code to do something tenuously coffee related …] exports.doSomethingCoffeeRelated = function () { … }; exports.usefulNumber = 4;
  • 38. CommonJS Runners  Various non-browser platforms  Browserify  Require.js
  • 39. CommonJS Runners  Various non-browser platforms  Node.JS, CouchDB, Narwhal, XULJet  The native environment for CommonJS modules  Synchronous loading makes perfect sense server-side  Closer model to non-browser scripting languages  Browserify  Require.js
  • 40. CommonJS Runners  Various non-browser platforms  Browserify  CommonJS modules for the browser  Build tool that takes CommonJS modules and compiles the whole app into a single script file  Lets node.js modules work directly in a browser  Require.js
  • 41. CommonJS Runners  Various non-browser platforms  Browserify  Require.js  Primarily an AMD script loader  Can support CommonJS style modules, hackily, with: define(function(require, exports) { var beanTypes = require(‚coffeeMachine/beanTypes‛); exports.favouriteBeanType = beanTypes[0]; });
  • 42. CommonJS Benefits  Code internals are encapsulated  Dependencies are explicitly named  Code is easily reusable  Simple clean syntax and conceptual model  Basically no boilerplate  Handles circular references better than AMD
  • 43. CommonJS Problems  Lots of magic involved  Doesn’t follow standard JavaScript conventions  No consideration of environment where loads are expensive  Ignores JavaScript’s inherent asynchronicity  Dependencies aren’t necessarily all obvious upfront
  • 44. ES6 Modules module ‚aCoffeeComponent‛ { import $ from ‘jquery’; import { NICE_BEANS as niceBeans } from ‚beanTypes‛; import ‘coffeeMachine/coffeeGrinder’ as grinder; export default function doSomethingCoffeeRelated() { … }; export var usefulNumber = 4; }
  • 45. ES6 Modules module ‚aCoffeeComponent‛ { import $ from ‘jquery’; import { NICE_BEANS as niceBeans } from ‚beanTypes‛; import ‘coffeeMachine/coffeeGrinder’ as grinder; export default function doSomethingCoffeeRelated() { … }; export var usefulNumber = 4; }
  • 46. ES6 Modules module ‚aCoffeeComponent‛ { import $ from ‘jquery’; import { NICE_BEANS as niceBeans } from ‚beanTypes‛; import ‘coffeeMachine/coffeeGrinder’ as grinder; export default function doSomethingCoffeeRelated() { … }; export var usefulNumber = 4; }
  • 47. ES6 Modules module ‚aCoffeeComponent‛ { import $ from ‚jquery‛; import { NICE_BEANS as niceBeans } from ‚beanTypes‛; import ‘coffeeMachine/coffeeGrinder’ as grinder; export default function doSomethingCoffeeRelated() { … }; export var usefulNumber = 4; }
  • 48. ES6 Module Benefits  Likely to be extremely well supported everywhere, eventually  More granular & powerful module import controls  New syntax, but otherwise fairly true to existing JS semantics  Fairly low on boilerplate  Handles circular references even better  Similar to other language concepts & syntax  Modules can be declared either inline, or nested, or externally
  • 49. ES6 Module Problems  Currently supported effectively nowhere  Not even final in the spec yet  Quite a lot of genuinely new syntax  import * is included, but is frowned upon in every other language  Powerful, but thereby comparatively quite complicated
  • 50. Which one do I use? IIFE: For tiny projects For trivial compatibility AMD: For most serious browser-based projects For a no-build pure-JS solution If you need to depend on non-JS content/events CommonJS: For anything outside a browser environment For anything in a browser where you might want Node modules ES6: If you yearn for the extremely bleeding edge And you live way in the future where it has real support
  • 51. Thank you Tim Perry Tech Lead & Open-Source Champion at Softwire @pimterry / github.com/pimterry / tim-perry.co.uk