History of
Web Development
JS Module
What is a module?
- Encapsulates code and data to implement a particular functionality
- Interface that lets clients to access its functionality in an uniform manner
- Packaged in a single unit, can be easily deploy and plugged into another module
In most programming language:
- Most cases, 1 file is 1 module
- Sometimes, multiple files packaged as 1 module
What is a module?
Once upon a time in a Vanilla JavaScript world
<body>
...
<script src="/lib/jquery.min.js"></script>
<script src="/index.js"></script>
</body>
// index.js
$(function() {
$('div').on('click', function() {
...
});
});
$ is in
GLOBAL SCOPE
<body>
...
<script src="/lib/jquery.min.js"></script>
<script src="/utils.js"></script>
<script src="/index.js"></script>
</body>
// utils.js
var pi = 3.142;
function area(radius) {
return pi * radius * radius;
}
function circumference(radius) {
return 2 * pi * radius;
}
<body>
...
<script src="/lib/jquery.min.js"></script>
<script src="/utils.js"></script>
<script src="/index.js"></script>
</body>
// index.js
console.log(area(5)); // 78.55
console.log(circumference(5)); // 31.42
console.log(pi); // 3.142
IF YOU WANT
LOCAL SCOPE
IIFE
(Immediately Invoked Function Expression)
// utils.js
var circle = (function() {
var pi = 3.142;
function area(radius) {
return pi * radius * radius;
}
function circumference(radius) {
return 2 * pi * radius;
}
return {
area,
circumference,
};
})();
// index.js
var length = circle.circumference(5)
console.log(pi); // throws pi is not defined
<body>
...
<script src="/lib/jquery.min.js"></script>
<script src="/utils.js"></script>
<script src="/index.js"></script>
</body>
// utils.js
var circle = (function() {
pi = 3.142;
function area(radius) {
return pi * radius * radius;
}
function circumference(radius) {
return 2 * pi * radius;
}
return {
area,
radius,
};
})();
// utils.js
"use strict"
var circle = (function() {
pi = 3.142; // throws error
function area(radius) {
return pi * radius * radius;
}
function circumference(radius) {
return 2 * pi * radius;
}
return {
area,
radius,
};
})();
SUMMARY
PROBLEMS
- INSTALLABILITY
- IMPORTABILITY
- SCOPEABILITY
INSTALLABILITY
How easy is it to install?
/project
/bower_components
/node_modules
/app
/bower.json
/package.json
<script src="bower_components/jquery/dist/jquery.min.js"></script>
npm install jquery@3.4.0
IMPORTABILITY
How easy is it to import?
You share everything through global scope
BUT LIFE IS STILL OKAY
FRONTEND =
SERVER SIDE RENDER +
CLIENT SIDE ATTACH EVENT
LISTENER
CommonJS
What I’m describing here is not a technical problem. It’s a matter of people getting together and making a decision to step forward and start building up something bigger and cooler together. | |
— Kevin Dangoor[1] |
require('./circle')
exports.pi = 3.142;
require is synchronous
require("./circle.js")
require("./circle.js")
- read content from "./circle.js"
- eval the content
- return what is assigned to exports
in Node.js
require("./circle.js")
- fetch content from "./circle.js"?
in Browser
require("./circle.js",
function (circle) {
//
})
script loaders
load("lib/jquery.min.js", callback);
const addedScript = new Set();
function load(url, callback) {
if (addedScript.has(url)) {
callback();
}
const script = document.createElement('script');
function cleanup() {
script.onload = script.onreadystatechange = script.onerror = null;
}
script.onload = script.onreadystatechange = function() {
document.body.appendChild(script);
cleanup();
};
script.onerror = function() {
callback(new Error());
cleanup();
}
script.src = url;
addedScript.add(url);
}
load("lib/jquery.min.js", callback);
import("lib/jquery.min.js").then(callback);
AMD
Asynchronous Module Definition
define(id?, dependencies?, factory)
// circle.js
define("circle", function() {
return {};
})
// main.js
define("main", ["jquery", "circle"], function(jquery, circle) {
//
})
(function(definition) {
const registry = {};
function require(mod) {
if (registry[mod]) {
return registry[mod];
}
const module = { exports: {} };
definition[mod](require, module, module.exports);
return registry[mod] = module.exports;
}
// kickstart
require('main');
})({
main: function(require, module, exports) {
const circle = require('circle');
console.log(circle.area(5));
},
circle: function(require, module, exports) {
exports.area = '...';
},
});
CommonJS
OR
AMD
YEAR 2015
ES Harmony (ES6)
Modules
import circle from './circle'
exports const pi = 3.142;
SCOPEABILITY
Scope pollution?
You share everything through global scope
IF YOU WANT
LOCAL SCOPE
IIFE
(Immediately Invoked Function Expression)
If your library want to export $,
you are out of luck!
goog.provide('tutorial.notepad'); goog.require('goog.dom'); tutorial.notepad.makeNotes = function(data) {
//...
goog.dom.appendChild(this.parent, data); };
// goog.provide('tutorial.notepad'); tutorial = tutorial || {}; tutorial.notepad = tutorial.notepad || {};
// goog.require('goog.dom'); goog = goog || {}; goog.dom = goog.dom || function() { ... }; tutorial.notepad.makeNotes = function(data) {
//...
goog.dom.appendChild(this.parent, data); };
AMD
// circle.js
define("circle", function() {
return {};
})
// main.js
define(["lodash", "underscore", "circle"], function(_, underscore, circle) {
//
})
// circle.js
const pi = 3.142;
export function area(radius) {}
export function circumeference(radius) {}
// main.js
import { area } from './circle';
console.log(area(5));
// bundle.js
function area(radius) {}
function circumeference(radius) {}
console.log(area(5));
// circle.js
const pi = 3.142;
export function area(radius) {}
export function circumeference(radius) {}
// square.js
export function area(side) {}
// main.js
import { area } from './circle';
import { area as squareArea } from './square';
console.log(area(5));
console.log(squareArea(5));
// bundle.js
function area$circle(radius) {}
function circumeference(radius) {}
function area$square(side) {};
console.log(area$circle(5));
console.log(area$square(5));
PROBLEMS
- INSTALLABILITY
- IMPORTABILITY
- SCOPEABILITY
REFERENCE
- Gao Wei
- Wu Jianbo
- Ten Zhi Yang
THANKS
JS Module
By Li Hau Tan
JS Module
- 1,716