JavaScript - Modules
author: Paul Kim
categories: js
tags: js
understanding CommonJS (i.e., require
and module.exports
) is what we use in Node.js
understand ES6 modules (i.e., import
and export
/ export default
). also, better understand its use. see source for better explanation with examples.
Module Formats & Module Loaders
Popular module formats in ES5 (AMD and CommonJS)
Popular loaders in ES5 (RequireJS and SystemJS)
AMD & RequireJS
CommonJS & SystemJS
ES6 features
ES6 modules
Transpilers
Bundlers
Webpack - module bundler
{%- comment -%}
notes about modular javascript
https://medium.com/computed-comparisons/commonjs-vs-amd-vs-requirejs-vs-es6-modules-2e814b114a0b
https://www.davidbcalhoun.com/2014/what-is-amd-commonjs-and-umd/
ES5 originally didn't include support for modules
first of all: we need modules!
why? because modules help us better organize and reuse our code
- our code is encapsulated inside the module
- this gives us better way to minimize polluting the global namespace unnecessarily
- our code is more reusable
all modern browsers support ES5, but ES5 doesn't support modules.
So developers came up with a lot of workarounds:
-
using vanilla JavaScript
- Singleton Pattern
- Constructor Pattern
These patterns are useful when using plain old JS
- it adds one value to the global scope per module
- it is modular so shouldn't depend on another module (not sure if i understand this part)
Module Formats & Module Loaders
- module format - a specific syntax that is required to interpret the code as a module
- loader - a third party tool that can help interpret specific module formats.
remember, there is no module format native to js in ES5. Since there is no native module format in ES5. So module formats in ES5 cannot be used without a module loader.
However, there is a module format native to js in ES6 (import/export) so it can be used without a loader
Popular module formats in ES5 (AMD and CommonJS)
- AMD - browser
- CommonJS - node
Popular loaders in ES5 (RequireJS and SystemJS)
- RequireJS - load AMD modules
- SystemJS - supports many different module formats
AMD & RequireJS
AMD syntax provides us with two new functions named define.
- first parameter is an array of dependencies
- second paramter is the function definition
define([‘./player’, ‘./scoreboard’], function() {
console.log('Creating a new scoreboard module');
function addResult(newResult) { ... }
function updateScoreboard() { ... }
return {
addResult: addResult,
updateScoreboard: updateScoreboard
}
});
we need to install requirejs
npm i --save bower-requirejs
and include it in your html:
<script data-main="js/app" src="node_modules/requirejs/require.js"></script>
CommonJS & SystemJS
scoreboard.js:
console.log('Creating a new scoreboard');
var results = [];
function addResult(newResult) {
results.push(newResult);
}
function updateScoreboard() {
...
}
//a little bit different way of doing it than the player module
module.exports = {
addResult: addResult,
updateScoreboard: updateScoreboard
};
and we use the require function to include our new scoreboard module
var scoreboard = require('./scoreboard.js')
scoreboard.addResult(result)
we need to install systemjs
npm i --save systemjs
and import/configure it
<script src = "node_modules/systemjs/dist/system.js"></script>
<script>
// configure systemJS
System.config({
meta: {
format: 'cjs' //cjs refers to CommonJS format
}
});
System.import('js/app.js'); //import systemJS
</script>
ES6 features
- class syntax
- let and const
- module support
ES6 modules
exporting modules
// include 'export' keyword
export function setName(name) { ... }
export function getName() { ... }
// include an export object with properties you want
function addResult() { ... }
function updateScoreboard() { ... }
export { addResult, updateScoreboard };
importing modules
// import entire modules
import * as scoreboard from ‘./scoreboard.js’;
scoreboard.updateScoreboard();
// import specific elements of a module
import { getName as getPlayerName, logPlayer } from ‘./player.js’;
function printGame() {
logPlayer();
console.log(getPlayerName() + “ is now playing”);
}
Transpilers
use babel to transpile your ES6/7/8 code into ES5
npm i -D babel-cli
npm i -D babel-preset-es2015
// get the destination of the transpiled code
cd node_modules/.bin/babel
js — — preset s es2015 — — out-dir build
// out-dir will specify where to put our transpiled code
Bundlers
Note: beware of the pitfalls of bundlers. when we bundle too many files at ounce, loading that one bundled file can take so long it will interrupt the user's experience instead of making it smoother.
Browserify:
npm i -D browserify
mkdir build
js/app.js --outfile build/bundle.js
Webpack - module bundler
webpack is a single tool that does bundling, transpling, etc at once. it will take modules with dependencies (even css, img, etc) and bundle them into static assets
module.exports = {
entry: './js/app.js', //an entry point for the application
output: {
path: './build', //location for output file
filename: 'bundle.js', //name of output file
},
module: {
loaders: [
{
test: /\.js$/, //run through files matching this regex
exclude: /node_modules/, //exclude these files
Loader: 'babel-loader', //use a babel loader
query: {
presets: ['es2015'], //use this babel preset
},
},
],
},
}
you can run the webpack
command found in ./node_modules/.bin/webpack
and include it in html
<script src = “./build/bundle.js”></script>
Source
https://medium.com/@crohacz_86666/basics-of-modular-javascript-2395c82dd93a http://www.jiehuang.net/wordPress/uncategorized/ecmascript/ https://medium.com/javascript-in-plain-english/javascript-modules-for-beginners-56939088f7d9 https://hacks.mozilla.org/2015/08/es6-in-depth-modules/ https://v8.dev/features/modules {%- endcomment -%}