JavaScript programs started off pretty small — most of its usage in the early days was to do isolated scripting tasks, providing a bit of interactivity to your web pages where needed, so large scripts were generally not needed. Fast forward a few years and we now have complete applications being run in browsers with a lot of JavaScript, as well as JavaScript being used in other contexts (Node.js, for example).
It has therefore made sense in recent years to start thinking about providing mechanisms for splitting JavaScript programs up into separate modules that can be imported when needed. Node.js has had this ability for a long time, and there are a number of JavaScript libraries and frameworks that enable module usage (for example, other CommonJS and AMD-based module systems like RequireJS, and more recently Webpack and Babel).
The good news is that modern browsers have started to support module functionality natively, …[11]
Therefore we say that a module in JavaScript is a piece of code
written to be used in various contexts, browser or serverside,
and easily incorporated where needed.
Modules are written into separate js files.
first.js
'use strict';
/*
* first.js
*/
export function doSomething(text) {
const elem = document.createElement('p');
elem.textContent = text;
document.body.appendChild(elem);
}
first.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Basic JavaScript Module Example</title>
<meta name="viewport" content="width=device-width, minimum-scale=1.0">
</head>
<body>
<header>
<h1>JS Modules in HTML5</h1>
</header>
<script type="module"> // import, requires type="module"
import {doSomething} from './first.js';
doSomething('Modules rock!'); // imported function in action
</script>
</body>
</html>
A word of warning: The file extension
.mjs is a mnemonic for JavaScript module files, just
as .js is a mnemonic for JavaScript files. For modules to
work the module file(s) must be referenced from HTML5 with
<script type="module" ...
ie with a type specification of module.
If you decide to use the recommended file extension
.mjs you must make sure that your web server
is configured to handle .mjs files in the same
way as it handles .js files. The web server must
do this by serving module files with a mime type of
application/javascript. This is done quite
simply by adding the second of the following two lines to
the configuration file mime.types.
application/javascript js
application/javascript mjs
Unfortunately the vast majority of hosting sites have not yet
updated their mime.types. Please nag them until
they have. Until then, you have to use the .js
extension at the cost of self documenting code.
The main benefits of using modules, is that HTML5 files
do not need script elements for all the
necessary JavaScript files.
Indeed how should the HTML5 writer know in detail what
is required. One is required,
of course, and that one must be referenced in the HTML5
and will, in turn, import the others as needed.
Let us illustrate that, and some more points, with another
example. The scenario of this example is filling some
available screen real estate with some content.
maintest.js
'use strict';
const $ = function (foo) {
return document.getElementById(foo);
};
const $q = function (foo) {
return document.querySelector(foo);
};
const greeting = function (bar) {
return `Hello ${bar}!`;
};
export {$, $q, greeting};maintesttest.js
'use strict';
import {$, greeting} from './maintest.js';
const greet = function () {
let here = $('main');
let g = document.createTextNode(greeting('world'));
here.appendChild(g);
}
window.addEventListener('load', greet);
indextest.html
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Basic JavaScript module example</title>
<style>
canvas {
border: 1px solid black;
}
</style>
<script type='module' src="./maintesttest.js"></script>
</head>
<body>
<header>
<h1>Modules in HTML</h1>
</header>
<main id='main'></main>
<footer>
© nml
</footer>
</body>
</html>
You will notice the essential aspects:
exports the functions it wants to share,
not necessarily all the functions should be shared.
Some might be for internal use in the module.
This example is more complex in that it contains more modules imported into the HTML5
$ in nQuery.js
'use strict';
/**
* nQuery, *the* JS Framework
*/
export const $ = function (foo) {
return document.getElementById(foo); // save keystrokes
}buildTttBoard2.js
'use strict';
/**
* buildTttBoard - Creates TicTacToe Board
*/
import {$} from './nQuery.js';
let buildTttBoard = function() {
const DIM = 3;
let div = $('ttt'); // points to id: ttt
let t = document.createElement('table');
t.style.border = '1px solid black';
t.style.height = '96%';
t.style.width = '96%';
t.style.margin = '1% auto';
for (let i = 0; i < DIM; i++) {
let r = document.createElement('tr');
for (let j = 0; j < DIM; j++) {
let c = document.createElement('td');
c.style.textAlign = 'center';
c.style.verticalAlign = 'middle';
c.style.fontWeight = '900';
c.style.fontSize = '40px';
c.style.border = '1px solid black';
c.style.height = '32%';
c.style.width = '32%';
c.addEventListener('click', function eh(e) {
e.target.appendChild(document.createTextNode('X'));
e.target.removeEventListener('click', eh);
});
r.appendChild(c);
}
t.appendChild(r);
}
div.appendChild(t);
}
export {buildTttBoard};thePage.js
'use strict';
/**
* createPage - Creates page content on load of minimal html
*/
import {$} from './nQuery.js';
import {buildTttBoard} from './buildTttBoard2.js';
let createPage = function() {
let b = $('bod'); // points to body
let h1 = document.createElement('h1');
let h1t = document.createTextNode('Some Page');
h1.appendChild(h1t);
h1.setAttribute('style', 'color: yellow'); // style one way
b.appendChild(h1);
let j = Math.floor(Math.random() * 9 + 1);
for (let i = 0; i < 9; i++) {
let d = document.createElement('div');
d.style.border = '1px solid blue'; // style another way
d.style.backgroundColor = 'silver'
d.setAttribute('class', 'fl'); // ref to stylesheet
if (i === j) {
d.style.backgroundColor = 'yellow';
d.setAttribute('id', 'ttt');
}
b.appendChild(d);
}
buildTttBoard();
}
window.addEventListener('load', createPage);indextest.html
<!doctype html>
<html>
<head>
<title>What Is This?</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="styles.css" rel="stylesheet"/>
<script type='module' src="./modules/thePage.js"></script>
</head>
<body id='bod'>
</body>
</html>