Javascript Design Patterns. AMD & commonJS. RequireJS Marc Torrent Vernetta
Javascript Design Patterns
A reusable solution that can be applied to commonly occurring problems in software design -in our case- in writing JavaScript Web application. What is a Pattern? Templates for how we solve problems - ones which can be used in quite a few different situations situations Addy Osmani
Three Main Benefits 1. Proven Solutions 2. Easily Reused 3. Expressive NOT EXACT SOLUTIONSSUPPORT DEVELOPERS
A Good Pattern 1. Solves a particular problem 2. Not an obvious solution 3. A proven described concept 4. Describe a relationship Display some recurring phenomenon: ❖ Fitness of purpose ❖ Usefulness ❖ Applicability
Antipatterns 1. Polluting global namespace 2. Strings to setTimeout and setInterval + eval() 3. Modify the Object prototype (very bad!!) 4. Javascript in an inline form 5. Use of document.write Knowledge for anti-patterns is critical for success !!!!
Antipatterns 1. Polluting global namespace 2. Strings to setTimeout and setInterval + eval() 3. Modify the Object prototype (very bad!!) 4. Javascript in an inline form 5. Use of document.write Knowledge for anti-patterns is critical for success !!!!
Design Pattern Types ➢ Creational ○ Factory Pattern ○ Constructor Pattern ○ Singleton Pattern ○ Prototype Pattern ➢ Structural ○ Module Pattern ○ Adapter Pattern ○ Decorator Pattern ○ Façade Pattern ○ Mixin Pattern ○ Flyweight Pattern ➢ Behavioral ○ Mediator Pattern ○ Observer Pattern Classes Objects
Creational Patterns
Constructor Pattern
Constructor Pattern - Prototype
Prototype Pattern
Sub-Classing
Mixin Pattern
Structural Patterns
Module Pattern - Object Literal
Module Pattern - IIFE
Module Pattern - Revealing
Behavioral Patterns
Observer Pattern - I SUBJECT STATE OBSERVERS LIST OBSERVER N O T I F Y CONCRETE SUBJECT CONCRETE OBSERVER UPDATE
Observer Pattern - II
Observer Pattern - III
Observer Pattern - IV
Observer Pattern - V
Observer Pattern - VI
Observer Pattern - VII
Publish/Subscribe Pattern - I PUBLISHER (SUBJECT) SUBSCRIBER EVENT AGGREGATOR SUBSCRIBER
Publish/Subscribe Pattern II
Publish/Subscribe Pattern III
Publish/Subscribe Pattern IV
Mediator Pattern - I SUBJECT SUBSCRIBER EVENT AGGREGATOR SUBSCRIBER MEDIATOR
Mediator Pattern - II
Mediator Pattern - III
Mediator Pattern - IV
Mediator Pattern - V
Modern Modular JavaScript Design Patterns
Module AModule BModule CModule N …... Application Modular Application Loosely Coupled Dependency Control Script Loader ➢ BROWSER: Asynchronous Module Definition (AMD) requireJS ➢ SERVER: commonJS Dependency Control
AMD Modules ➢ Defining modules with dependencies to other modules. ➢ The module and dependencies can be asynchronously loaded. ➢ Both modules are asynchronous and highly flexible by nature ➢ Removes the tight coupling between code and module identity
AMD Modules Advantages ● Provides a clear proposal for how to approach defining flexible modules. ● Significantly cleaner than the present global namespace and tag solutions many of us rely on. There's a clean way to declare stand-alone modules and dependencies they may have. ● Module definitions are encapsulated, helping us to avoid pollution of the global namespace. ● Most AMD loaders support loading modules in the browser without a build process. ● Provides a "transport" approach for including multiple modules in a single file. ● It's possible to lazy load scripts if this is needed.
AMD Modules - define vs require define( module_id /*optional*/, [dependencies] /*optional*/, definition function /*function for instantiating the module or object*/ ); require( [dependencies] /*required*/, complete function /*function for instantiating the dependecies*/ );
AMD Modules - define vs require define([“url_to_anonymous_module”, “named_module_id”], function(ModuleA, ModuleB) { function doCoolStuff(a) { ModuleA.cool(a, ModuleB.getCool()); } return { cool: doCoolStuff }; } ); require([“myModule”], function(moduleC) { var superCool = “super cool”; moduleC.cool(superCool); });
requireJS ➢ Library for working with AMD modules. Asynchronous script loader and dependency manager. ➢ Easy naming definition with a json configuration. Prepare non AMD modules for other AMD modules as its dependency management stays untouched. ➢ Optimization tool for bundling modules in one or many optimized, uglified and minimized module. ➢ With plugin extension for loading non JS scripts, like CSS, JSON, JSONP, etc… ➢ commonJS wrapper for styling AMD module loading with commonJS syntax and reducing verbosity.
requireJS and AMD require([dependencies], function(depA, depB,...){}); requirejs([dependencies], function(depA, depB,...){}); define() function and module definition remains exactly the same requirejs.config({ baseUrl: ‘path_to_where_scripts_are’, paths: { name_of_a_module: ‘relative_path_of_the_module’, other_module_name: ‘relative_path_of_other_module’ }, shim: { name_of_a_module: { exports: ‘Foo’, }, other_module_name: [“name_of_a_module”] } });
requireJS and HTML requirejs([“app”], function(app) { app.start(); });
commonJS modules ➢ Reusable piece of JavaScript which exports specific objects made available to any dependent code. ➢ Unlike AMD, there are typically no function wrappers around such modules. ➢ Two primary parts: a free variable named exports which contains the objects a module wishes to make available to other modules and a require function that modules can use to import the exports of other modules ➢ Only able to define objects which can be tedious to work with if we're trying to obtain constructors out of them ➢ Useful for Server side because it can use io, fs, system, etc..
commonJS in depth var libA = require(‘package/libA’), libB = require(‘package/libB’); function foo(){ libA.log( ‘hello world!’ ); } exports.foo = foo; exports.bar = function bar() { libB.myFunc(); }; var foobar = require(‘foobar’); foobar.foo(); foobar.bar();
requireJS with commonJS style define(function(require) { var moduleA = require(‘moduleA’), moduleB = require(‘moduleB’); function doCoolStuff(a) { moduleA.cool(a, moduleB.getCool()); } return { cool: doCoolStuff }; } );
Library App with RequireJS & AMD
Thanks for your attention! Leave your questions on the comments section