JavaScript Modules

Dr. Greg Bernstein

September 8th, 2019

Javascript Modules

ES6 Modules Readings/References

General JavaScript Modules

Why JavaScript Modules

  • Almost all computer languages support breaking programs into more manageable pieces.
  • Need to avoid “name collisions” of variables, functions, etc…
  • Promote code reuse via libraries and frameworks.

State of JavaScript Modules

  • JavaScript initially did not have any module support as part of the language.
  • A number of design patterns were used instead, these tend to be non-optimal, confusing or both.
  • First “de facto” module system was called CommonJS, there were more advanced systems such as AMD, UMD, and now we have standard modules in ES6.

Node.js Modules

Node.js Modules

  • Based on require() method and module.exports object.
  • Assign external module to a variable via require(path) function.
  • Determine what to export from a module by adding to the the module.exports object.

Node.js Export 1

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"};

Node.js Import 1

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);

Node.js Export 2

Reassign module.exports to an new object

module.exports = {
    wind(){
        return Math.random()*25;
    },
    kite: "12m",
    helmet: true,
    lines: "25m",
    bar: "North control bar"};

Node.js Import 2

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);

Node.js Export 3

Shortcut via exports object

exports.extra = "Hello CommonJS Modules";
exports.tide = function() {
                return Math.random()*6;
};

Node.js Import 3

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`);

ES6 Modules

ES6 Modules

Part of the JavaScript language standard

  • Just arriving in browsers in 2018, long used in front-end frameworks via the Babel transpiler and Webpack bundler tools.
  • You choose what to export from a module (file) via the export statement (many variations).
  • You choose what to import to a module via the import statement (many variations).

ES6 Export 1

Explicit export list

let wind = 20;
let tide = 5.2;
let board = "Wind Foil by Alex";
let foil = {strut: "1m", frontWing: "80cm", rearWing: "20cm"};

export {wind, tide, board, foil};

ES6 Export 2

Default export

export default {
    wind(){
        return Math.random()*25;
    },
    kite: "12m",
    helmet: true,
    lines: "25m",
    bar: "North control bar"};

ES6 Import

A number of variations to help control namespaces

// Imports everything and puts it in the windsurf object
import * as windsurf from './simpleES6a.js';
// Imports the default and assigns it to the kitesurf object
import kitesurf from './simpleES6b.js';
// Chooses specific items to import
import {tide, extra} from './simpleES6c.js';

ES6 Modules Browser Example

Not Quite There Yet…

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>ES6 Module Test</title>
  </head>
  <body>
  <h1>ES6 Module Test</h1>
  <p>I hear modern browsers now support modules!</p>
  <p>Open the developer console to see.</p>
<script type="module">
import * as windsurf from './simpleES6a.js';
import kitesurf from './simpleES6b.js';
import {tide, extra} from './simpleES6c.js';

console.log("Stuff I imported from simpleCJSa.js:");
console.log(windsurf.board);
console.log(windsurf.foil.strut);

console.log("Stuff I imported from simpleCJSb.js:");
console.log(`wind: ${kitesurf.wind().toFixed(1)} mph`);
console.log(kitesurf.kite);

console.log("Stuff I imported from simpleCJSc.js:");
console.log(extra);
console.log(`tide level ${tide().toFixed(1)} feet`);
</script>

  </body>
</html>

Bundlers

What Do They Do

Bundlers are just to combine many JavaScript modules into a few JavaScript modules for deployment purposes.

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.

Other Bundler Features

Many modern JavaScript Bundlers provide many more functions such as

  • CSS bundling, code and CSS size minimization
  • JSON integration
  • Development Server, File Watcher, Automatic rebuild

How Do They Work?

Extremely high level view:

Bundlers look at file dependencies such as indicated by <import>, <script>, <link> tags and more. They build up a dependency graph of the various files and then get to work combining them appropriately.

Webpack

Rollup.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.

Parcel

We’ll use Parcel in this class.

Blazing fast, zero configuration web application bundler

  • Zero or near zero configuration
  • Global install rather than per project
  • Development Features: file watcher, hot module replacement, web server

Parcel Install and Use

  • Global Installation: npm install -g parcel-bundler
  • Getting Started
  • package.json additions:
{
  "scripts": {
    "dev": "parcel <your entry file>",
    "build": "parcel build <your entry file>"
  }
}

Useful Parcel Options

  • Port for development server:

parcel <your entry file> -p <port number>

  • Production with relative URLs:

parcel build <your entry file> --public-url ./