Michael Kühnel
Frontend Developer working for Micromata 👨🏼💻
A module is a reusable piece of code that encapsulates implementation details and exposes public methods so it can be used by other code.
In short: Do give code structure and increase maintainibility
// modulName.js
var modulName = (function() {
var privateVar = 'Ben Cherry';
var publicVar = 'Hey there!';
function _privateMethod() {
console.log('Name:' + privateVar);
}
function publicSetName(strName) {
privateVar = strName;
}
function publicGetName() {
privateMethod();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
// otherFile.js
modulName.setName('Paul Kinlan');
// modulName.js
var appName = window.appName || {};
appName.modulName = (function($) {
'use strict';
var yourPublicMethod = function(message) {
console.info(message);
};
var _yourPrivateMethod = function(message) {
console.info(message);
};
$(function() {
_yourPrivateMethod('Hi Private.');
});
// Return functions to make them accessible from outside.
return {
yourPublicMethod: yourPublicMethod
};
})(jQuery);
// otherFile.js
$(function() {
'use strict';
appName.modulName.yourPublicMethod('Hi public.');
});
Before ES6, JavaScript did not have an official syntax to define modules. Therefore, smart developers came up with various formats to define modules in JavaScript.
Some of the most widely adapted and well known formats are:
The AMD format is used in browsers and uses a define function to define modules
// Filename: foo.js
// Calling define with a dependency array and a factory function
define(['jquery'], function($) {
// Methods
function myFunc() {};
// Exposed public methods
return myFunc;
});
You will only find this in legacy projects
Was used with require.js in the browser or transpiled with r.js
The CommonJS format is used in Node.js and uses require and module.exports to define dependencies and modules
// Filename: foo.js
// Dependencies
var $ = require('jquery');
// Methods
function myPrivateMethod(){};
function myPublicMethod(){};
// Expose public method (single)
module.exports = myPublicMethod;
// Filename: foo.js
// Dependencies
var $ = require('jquery');
var _ = require('underscore');
// Methods
function a() {}; // Private because it's omitted from module.exports
function b() {}; // Public because it's defined in module.exports
function c() {}; // Public because it's defined in module.exports
// Exposed public methods
module.exports = {
b: b,
c: c
};
Default module system in Node.js
Can be used in the browser with module bundlers like webpack and browserify.
UMD modules can be used both in the browser and in Node.js (and can be consumed by module bundlers)
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS-like
module.exports = factory(require('jquery'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.jQuery);
}
}(this, function($) {
// Methods
function myFunc() {};
// Exposed public method
return myFunc;
}));
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery', 'underscore'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS-like
module.exports = factory(require('jquery'), require('underscore'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.jQuery, root._);
}
}(this, function($, _) {
// Methods
function a() {}; // Private because it's not returned
function b() {}; // Public because it's returned
function c() {}; // Public because it's returned
// Exposed public methods
return {
b: b,
c: c
}
}));
Preferred format for publishing libraries
Can be used everywhere. Creation of UMD modules can be automated with module bundlers rollup.
As of ES6, JavaScript has a native module format which can be used in modern browsers and can be consumed by module bundlers (and will be useable in Node.js in the future)
// lib.js
// Export the function
export function publicFunction() {
console.log('Hello');
}
// Do not export the function
function somePrivateFunction() {
// ...
}
It uses an export token to export a modules public API:
and an import token to import parts that a module exports:
// otherFile.js
import { sayHello } from './lib';
sayHello(); // => Hello
// otherFile.js
import { sayHello as say } from './lib';
say(); // => Hello
We can even give imports an alias using as:
or load an entire module at once:
// otherFile.js
import * as lib from './lib';
lib.sayHello(); // => Hello
// lib.js
// Export default function
export default function sayHello(){
console.log('Hello');
}
// Export non-default function
export function sayGoodbye(){
console.log('Goodbye');
}
The format also supports default exports:
which you can import like this:
// otherFile.js
import sayHello, { sayGoodbye } from './lib';
sayHello(); // => Hello
sayGoodbye(); // => Goodbye
// lib.js
// Export default function
export default function sayHello(){
console.log('Hello');
}
// Export non-default function
export function sayGoodbye(){
console.log('Goodbye');
}
// Export simple value
export const apiUrl = '...';
// Export object
export const settings = {
debug: true
}
You can export not only functions, but anything you like:
You should use ES6 modules if your a about to start a new project with clientside JavaScript
With the lack of native browser support you should combine Babel with a module loader like System.js or with module bundler like webpack or browserify.
Twitter: @mkuehnel
email: mail@michael-kuehnel.de
By Michael Kühnel
This presentation describes module formats used in the JavaScript world.