History of

Web Development

 

JS Module

What is a module?

  • Encapsulates code and data to implement a particular functionality
  • Interface that lets clients to access its functionality in an uniform manner
  • Packaged in a single unit, can be easily deploy and plugged into another module

In most programming language:

  • Most cases, 1 file is 1 module
  • Sometimes, multiple files packaged as 1 module

What is a module?

Once upon a time in a Vanilla JavaScript world

<body>

      ...

      <script src="/lib/jquery.min.js"></script>

      <script src="/index.js"></script>

</body>

// index.js

$(function() {

    $('div').on('click', function() {

          ...

    });

});

$ is in

GLOBAL SCOPE

<body>

      ...

      <script src="/lib/jquery.min.js"></script>

      <script src="/utils.js"></script>

      <script src="/index.js"></script>

</body>

// utils.js

var pi = 3.142;

 

function area(radius) {

    return pi * radius * radius;

}

 

function circumference(radius) {

    return 2 * pi * radius;

}

<body>

      ...

      <script src="/lib/jquery.min.js"></script>

      <script src="/utils.js"></script>

      <script src="/index.js"></script>

</body>

// index.js

console.log(area(5)); // 78.55

console.log(circumference(5)); // 31.42

 

console.log(pi); // 3.142

IF YOU WANT

LOCAL SCOPE

IIFE

(Immediately Invoked Function Expression)

// utils.js

var circle = (function() {

    var pi = 3.142;

 

    function area(radius) {

        return pi * radius * radius;

    }

 

    function circumference(radius) {

        return 2 * pi * radius;

    }

 

    return {

        area,

        circumference,

    };

})();

// index.js

var length = circle.circumference(5)

 

console.log(pi); // throws pi is not defined

<body>

      ...

      <script src="/lib/jquery.min.js"></script>

      <script src="/utils.js"></script>

      <script src="/index.js"></script>

</body>

// utils.js

var circle = (function() {

    pi = 3.142;

 

    function area(radius) {

        return pi * radius * radius;

    }

 

    function circumference(radius) {

        return 2 * pi * radius;

    }

 

    return {

        area,

        radius,

    };

})();

// utils.js

"use strict"

var circle = (function() {

    pi = 3.142// throws error

 

    function area(radius) {

        return pi * radius * radius;

    }

 

    function circumference(radius) {

        return 2 * pi * radius;

    }

 

    return {

        area,

        radius,

    };

})();

SUMMARY

PROBLEMS

  • INSTALLABILITY
  • IMPORTABILITY
  • SCOPEABILITY

INSTALLABILITY

How easy is it to install?

/project

    /bower_components

    /node_modules

    /app
    /bower.json
    /package.json

<script src="bower_components/jquery/dist/jquery.min.js"></script>

npm install jquery@3.4.0

IMPORTABILITY

How easy is it to import?

You share everything through global scope

BUT LIFE IS STILL OKAY

FRONTEND =

 

   SERVER SIDE RENDER +

   CLIENT SIDE ATTACH EVENT

   LISTENER

CommonJS

What I’m describing here is not a technical problem. It’s a matter of people getting together and making a decision to step forward and start building up something bigger and cooler together.  
— Kevin Dangoor[1]

require('./circle')

exports.pi = 3.142;

require is synchronous

require("./circle.js")

require("./circle.js")

  1. read content from "./circle.js"
  2. eval the content
  3. return what is assigned to exports

in Node.js

require("./circle.js")

  1. fetch content from "./circle.js"?

in Browser

require("./circle.js", 

  function (circle) {

      //

  })

script loaders

load("lib/jquery.min.js", callback);

const addedScript = new Set();

 

function load(url, callback) {

    if (addedScript.has(url)) {

        callback();

    }

    const script = document.createElement('script');

 

    function cleanup() {

        script.onload = script.onreadystatechange = script.onerror = null;

    }

 

    script.onload = script.onreadystatechange = function() {

        document.body.appendChild(script);

        cleanup();

    };

 

    script.onerror = function() {

        callback(new Error());

        cleanup();

    }

    script.src = url;

 

    addedScript.add(url);

}

load("lib/jquery.min.js", callback);

import("lib/jquery.min.js").then(callback);

AMD

Asynchronous Module Definition

define(id?, dependencies?, factory)

// circle.js

define("circle", function() {

      return {};

})

 

// main.js

define("main", ["jquery", "circle"], function(jquery, circle) {

      //

})

(function(definition) {

      const registry = {};

 

      function require(mod) {

            if (registry[mod]) {

                  return registry[mod];

            }

 

            const module = { exports: {} };

            definition[mod](require, module, module.exports);

            return registry[mod] = module.exports;

      }

 

      // kickstart

      require('main');

})({

      main: function(require, module, exports) {

            const circle = require('circle');

            console.log(circle.area(5));

      },

      circle: function(require, module, exports) {

            exports.area = '...';

      },

});

CommonJS

OR

AMD

YEAR 2015

ES Harmony (ES6)

Modules

import circle from './circle'

exports const pi = 3.142;

SCOPEABILITY

Scope pollution?

You share everything through global scope

IF YOU WANT

LOCAL SCOPE

IIFE

(Immediately Invoked Function Expression)

If your library want to export $,

you are out of luck!

goog.provide('tutorial.notepad');

goog.require('goog.dom');

tutorial.notepad.makeNotes = function(data) {
  //...
  goog.dom.appendChild(this.parent, data);
};
// goog.provide('tutorial.notepad');
tutorial = tutorial || {};
tutorial.notepad = tutorial.notepad || {};
// goog.require('goog.dom');
goog = goog || {};
goog.dom = goog.dom || function() { ... };

tutorial.notepad.makeNotes = function(data) {
  //...
  goog.dom.appendChild(this.parent, data);
};

AMD

// circle.js

define("circle", function() {

      return {};

})

 

// main.js

define(["lodash", "underscore", "circle"], function(_, underscore, circle) {

      //

})

// circle.js

const pi = 3.142;

export function area(radius) {}

export function circumeference(radius) {}

 

// main.js

import { area } from './circle';

console.log(area(5));

// bundle.js

function area(radius) {}

function circumeference(radius) {}

 

console.log(area(5));

// circle.js

const pi = 3.142;

export function area(radius) {}

export function circumeference(radius) {}

 

// square.js

export function area(side) {}

 

// main.js

import { area } from './circle';

import { area as squareArea } from './square';

console.log(area(5));

console.log(squareArea(5));

// bundle.js

function area$circle(radius) {}

function circumeference(radius) {}

function area$square(side) {};

 

console.log(area$circle(5));

console.log(area$square(5));

PROBLEMS

  • INSTALLABILITY
  • IMPORTABILITY
  • SCOPEABILITY

REFERENCE

  • Gao Wei
  • Wu Jianbo
  • Ten Zhi Yang

THANKS

JS Module

By Li Hau Tan

JS Module

  • 1,654