Dr. Greg Bernstein
Updated September 13th, 2021
MDN import, MDN export. Syntax and usage examples.
Historical Perspective: JavaScript Module Guide. Goes over early design patterns that you may still encounter, CommonJS, AMD, UMD, oh my.
Node.js Modules. Based on CommonJS.
Part of the JavaScript language standard
Explicit export
list from foilGear.js
let sails = ["Maui 7.7", "S2 7.0", "Maui 6.3", "Maui 5.5"];
let masts = ["Maui 460", "Maui 430", "Maui 400"];
let board = "Wind Foil by Alex";
let foil = { strut: "1m", frontWing: "80cm", rearWing: "20cm", brand: "F4" };
export { sails, masts, board, foil };
Default export
from waveGear.js
export default {
board: "Fanatic FreeWave 88",
sails: ["Maui Global 5.8", "North Natural 5.4", "North Natural 5.0"],
masts: ["Maui Gladiator RDM 430", "North Gold 400"],
boom: "Maui Carbon Wave"
};
Functions are easy to export
from conditions.js
function wind() { // random wind in MPH
return Math.random() * 25;
};
function tide() { // random tide in feet
return Math.random() * 6;
};
export { tide, wind };
Browser use (with an HTTP server)
<script type="module"> // Must have "module" for this to work
import * as foilGear from './foilGear.js';
import waveGear from './waveGear.js';
import {tide, wind} from './conditions.js';
console.log("Stuff I imported from foilGear.js:");
console.log(foilGear);
console.log("Stuff I imported from waveGear.js:");
console.log(waveGear);
console.log("Conditions");
console.log(`wind: ${wind().toFixed(1)} mph,`);
console.log(`tide level ${tide().toFixed(1)} feet`);
</script>
Node.js added support for ES6 (ECMAScript) modules in version 13. Hence version 14 is the first LTS (long term support) version with this support so we will start using it.
*.mjs
FilesBy default Node.js treats files ending in .mjs
as modern ES6 modules and interprets import
and export
according to the JavaScript standards. Files ending .js
are interpreted as regular Node.js and interprets require
and exports
“keywords” according to CommonJS module conventions. Hence we will use .mjs
file extensions in this class for most of our Node.js work.
From the file nodeES6Ex.mjs
:
import * as foilGear from './foilGear.mjs';
import waveGear from './waveGear.mjs';
import { tide, wind } from './conditions.mjs';
console.log("Stuff I imported from foilGear.mjs:");
console.log(foilGear);
console.log("Stuff I imported from waveGear.mjs:");
console.log(waveGear);
console.log("Conditions");
console.log(`wind: ${wind().toFixed(1)} mph,`);
console.log(`tide level ${tide().toFixed(1)} feet`);
Bundlers are just used to combine many JavaScript modules into a few JavaScript modules for deployment purposes.
Modern bundlers understand ES6 module syntax
The output files from a bundler are then included in an HTML page with <script>
and <link>
tags as appropriate.
This relieves the browser of module management for now.
Modern JavaScript Bundlers provide more functions such as
Extremely high level view:
Bundlers look at file dependencies such as indicated by <import>
, <script>
, <link>
tags, ES6 import
statements, and more. They build up a dependency graph of the various files and then get to work combining them appropriately.
All run in Node.js
Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger and more complex, such as a library or application. It uses the new standardized format for code modules included in the ES6 revision of JavaScript, instead of previous idiosyncratic solutions such as CommonJS and AMD.
We’ll use Parcel (v2) in this class.
Blazing fast, zero configuration web application bundler
npm install --save-dev parcel
node_modules/.bin/parcel index.html
parcel <your entry file> -p <port number>
parcel build <your entry file> --public-url ./
package.json
EntriesFor convenience add these to your package.json
:
"source": "index.html",
"scripts": {
"start": "parcel",
"build": "parcel build --public-url ./",
},
package.json
Scriptsnpm start
npm run-script build
From the file BundlerEx/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Bundler Based ES6 Module Example</title>
</head>
<body>
<h1>Bundler Based ES6 Module Test</h1>
<p>Open the developer console to see.</p>
<script src="main.js" type="module"></script>
</body>
</html>
main.js
imports all the others JavaScript files like in the first ES6 example
import * as foilGear from './foilGear.js';
import waveGear from './waveGear.js';
import { tide, wind } from './conditions.js';
console.log("Stuff I imported from foilGear.js:");
console.log(foilGear);
console.log("Stuff I imported from waveGear.js:");
console.log(waveGear);
console.log("Conditions");
console.log(`wind: ${wind().toFixed(1)} mph,`);
console.log(`tide level ${tide().toFixed(1)} feet`);
Notice multiple JavaScript files
On server bundlerTest
require()
method and module.exports
object.require(path)
function.module.exports
object.Just add extra fields to the module.exports
object:
module.exports.wind = 20;
module.exports.tide = 5.2;
module.exports.board = "Wind Foil by Alex";
module.exports.foil = {strut: "1m", frontWing: "80cm", rearWing: "20cm"};
Use require()
function to assign exported “stuff” to a variable:
const windsurf = require('./simpleCJSa');
console.log("Stuff I imported from simpleCJSa.js:");
console.log(windsurf.board);
console.log(windsurf.foil.strut);
Reassign module.exports
to an new object
module.exports = {
wind(){
return Math.random()*25;
},
kite: "12m",
helmet: true,
lines: "25m",
bar: "North control bar"};
Same use of require()
function
const kitesurf = require('./simpleCJSb');
console.log("Stuff I imported from simpleCJSb.js:");
console.log(`wind: ${kitesurf.wind().toFixed(1)} mph`);
console.log(kitesurf.kite);
Shortcut via exports
object
exports.extra = "Hello CommonJS Modules";
exports.tide = function() {
return Math.random()*6;
};
Same use of require()
function
const stuff = require('./simpleCJSc');
console.log("Stuff I imported from simpleCJSc.js:");
console.log(stuff.extra);
console.log(`tide level ${stuff.tide().toFixed(1)} feet`);