- Lalitha Iyer
@Iyer_Lalitha1
Software developer for ~ 7 years
Key Concepts
Modularity as a concept dates back to as early as 1950 with languages like JOVIAL & COBOL that provided library capabilities
Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality. " - Wikipedia
https://en.wikipedia.org/wiki/Asynchronous_module_definition
https://en.wikipedia.org/wiki/Asynchronous_module_definition
Explicit Dependency References
&
Module Graph
Root
Module6
Module1
Module2
Module4
Module5
1995
Birth of Javascript
1997
EcmaScript
1999
ES3 released
2005
AJAX & Gmail
2009-2014
ServerJS/Common JS
Node.js
NPM
vendor wars
standardization
jQuery
CSS frameworks
< script >
global namespace
Object Literal
module namespace
Module Pattern
IIFE
CJS, AMD
module loaders
browserify
webpack
module bundlers
js on server
2015
ES6
SPA frameworks
Bower
front end
package manager
server
client
scripting
SoC, Encapsulation
&
NameSpacing
Standardized Modules
SPA
es module
Encapsulation
Namespacing
Explicit dependency references
Explicit export
js on many platforms
2019
ES modules supported on browser and node
es modules
CJS, AMD
<html>
<head>
<script type='text/javascript'>
var onClick = function (type) {
var name = document.getElementById('name').value;
var greeting = 'hello'
if (type === 'custom') {
greeting = document.getElementById('greeting').value
}
showGreeting(getGreeting(name, greeting));
}
function getGreeting(name, greeting) {
return name + '' + greeting
}
function showGreeting(greeting) {
alert(greeting);
}
</script>
</head>
<body>
<form>
<input type='text' id='name'> Enter you name </input>
<input type='text' id='greeting'> Enter you Greeting </input>
<button onclick='onClick()'>Show Greeting</button>
<button onclick='onClick("custom")'>Show Custom Greeting</button>
</form>
</body>
</html>
Inline Script
<!–– Greeting Applicaiton -->
<html>
<head>
<script src='./greeting.js' type='text/javascript'></script>
<script>
var onClick = function (type) {
var name = document.getElementById('name').value;
var greeting = 'hello'
if (type === 'custom') {
greeting = document.getElementById('greeting').value
}
showGreeting(getGreeting(name, greeting));
}
</script>
</head>
<body>
<form>
<input type='text' id='name'> Enter you name </input>
<input type='text' id='greeting'> Enter you Greeting </input>
<button onclick='onClick()'>Show Greeting</button>
<button onclick='onClick("custom")'>Show Custom Greeting</button>
</form>
</body>
</html>
External Script
// Greeting.js
function getGreeting(name, greeting) {
return name + '' + greeting
}
function showGreeting(greeting) {
alert(greeting);
}
var greetingObject = {
name: "",
greeting: "hello",
init: function(name, greeting) {
this.name = name;
this.greeting = greeting;
},
getGreeting: function() {
return this.greeting + " " + this.name;
},
showGreeting: function() {
alert(this.getGreeting());
},
printGreeting: function() {
console.log(this.getGreeting());
}
};
Object Literal & Namespacing
var onClick = function (type) {
var name = document.getElementById('name').value;
var greeting = 'hello'
if (type === 'custom') {
greeting = document.getElementById('greeting').value
}
greetingObject.init(name, greeting);
greetingObject.showGreeting(greetingModule.getGreeting();
}
// namespacing & encapsulation
// Module pattern using IIFE
var greetingModule = (function() {
// private, function scope
var name = "";
var greeting = "hello";
// public
function init(n, g) {
name = n;
greeting = g;
}
// private
function getGreeting() {
return greeting + " " + name;
}
// public
function showGreeting() {
alert(getGreeting());
printGreeting(getGreeting());
}
// Object literal
return {
init,
showGreeting
};
})();
<html>
<head>
<script src='./greeting-module.js' type='text/javascript'></script>
<script type='text/javascript'>
var onClick = function (type) {
var name = document.getElementById('name').value;
var greeting;
if (type === 'custom') {
greeting = document.getElementById('greeting').value
}
greetingModule.init(name, greeting);
greetingModule.showGreeting();
}
</script>
</head>
<body>
<form>
<input type='text' id='name'> Enter you name </input>
<br /> <br />
<input type='text' id='greeting'> Enter you Greeting </input>
<br /> <br />
<button onclick='onClick()'>Greeting</button>
<button onclick='onClick("custom")'>Custom Greeting</button>
</form>
</body>
</html>
Module IIFE Pattern
A closure is the combination of a function bundled together (enclosed) with references to its surrounding state
" -MDN
Function Definition
function sayHi() {
alert("Hello, World!");
}
// Function expression
var sayHi = function() {
alert("Hello, World!");
}
// Function expression
(function(){
alert('hello world')
})
// IIFE
(function(){
alert('hello world')
})()
Function Expression
// display.js
let displayFunction;
if (process) {
displayFunction = console.log;
} else {
displayFunction = alert;
}
module.exports = displayFunction;
// greeting.js
const display = require("./display");
let name = "";
let greeting = "hello";
function init(name, greeting) {
name = name;
greeting = greeting;
}
function getGreeting() {
return greeting + " " + name;
}
function showGreeting() {
display(getGreeting());
}
module.exports = {
init,
showGreeting
};
Explicit dependency reference
Explicit export
declaration
Loaders
- Node one of the first the adopt
(function(require, module) {
// display.js
let displayFunction;
//If node.js return function console.log
if (!process.browser) {
displayFunction = console.log;
} else {
displayFunction = alert;
}
module.exports = displayFunction;
})
let cache = {};
function require(moduleIdentifier) {
// Resolve the module
let resolvedModuleId = resolve(moduleIdentifier);
// look up module cache
if(cache[resolvedModuleId])
return cache[resolvedModuleId];
}
// load module
let moduleSrc = load(resolvedModuleId);
// Wrap source in a function expression
let wrappedSource = wrap(moduleSrc);
// Evaluate module
let result = wrappedSource.call(require, {});
// Cache result
cache[moduleIdentifier] = result;
}
Require function - Module Loading
How Require Works - From James N. Snell
// greeting.js
define(["display"], function(display) {
return function() {
let name = "";
let greeting = "hello";
function init(name, greeting) {
name = name;
greeting = greeting;
}
function getGreeting() {
return greeting + " " + name;
}
function showGreeting() {
display(getGreeting());
}
return {
init,
showGreeting
};
};
});
// display.js
define(function() {
return function() {
let displayFunction;
if (process) {
displayFunction = console.log;
} else {
displayFunction = alert;
}
};
});
// main.js
define(["greeting"], function() {
return function() {
let submitButton = document.querySelector(".submit");
submitButton.addEventListener("click", () => {
showGreeting(document.getElementById("name").value);
});
};
});
AMD Define
<html>
<head>
<script data-main="main" src="scripts/require.js"></script>
</head>
<body>
<form>
<input type='text' id='name'> Enter you name </input>
<button id='greeting'>Greeting</button>
</form>
</body>
</html>
// main.js
const greetingModule = require("./greeting");
let submitButton = document.querySelector(".submit");
submitButton.addEventListener("click", () => {
showGreeting(document.getElementById('name').value);
});
module.exports = {};
// We use a bundler to assemble the modules in a single bundle
browserify main -o bundle.js
Module6
Module4
Module5
<html>
<head>
<script src='./bundle.js' type='text/javascript'></script>
</head>
<body>
<form>
<input type='text' id='name'> Enter you name </input>
<button id='greeting'>Greeting</button>
</form>
</body>
</html>
main
greeting
display
(function(modules) {
// The module cache
var installedModules = {};
function __webpack_require__(moduleId) {
// Check if module is in cache
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
} // Create a new module (and put it into the cache)
var module = (installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
}); // Execute the module function
modules[moduleId].call(__webpack_require__, module);
return module.exports;
}
// execute the entry point
return __webpack_require__("main.js");
})({
"./display.js": (function(require, module) {
let displayFunction;
if (process) {
displayFunction = console.log;
} else {
displayFunction = alert;
}
module.exports = displayFunction;
}),
"./greeting.js": (function(require, module) { // src }),
"./main.js": (function(require, module) { // src })
});
webpack bundle
/***** greeting.mjs ******/
import { display } from "./display";
let name = "";
let greeting = "hello";
function init(name, greeting) {
name = name;
greeting = greeting;
}
function getGreeting() {
return greeting + " " + name;
}
function showGreeting() {
display(getGreeting());
}
export { init, showGreeting };
/*** display.mjs ***/
let display;
if (process) {
display = console.log;
} else {
display = alert;
}
export { display };
/** main.mjs **/
import { showGreeting } from "./greeting";
let submitButton = document.querySelector(".submit");
submitButton.addEventListener("click", () => {
showGreeting(document.getElementById('name').value);
});
<html>
<head>
<script type="module" src="main.mjs"></script>
</head>
<body>
<form>
<input type='text' id='name'> Enter you name </input>
<input type='text' id='greeting'> Enter you Greeting </input>
<button onclick='onClick()'>Greeting</button>
<button onclick='onClick("custom")'>Custom Greeting</button>
</form>
</body>
</html>
The Best is yet to Come !
Raise the level of Abstraction
Lalitha Iyer
@Iyer_Lalitha1