Modules in javascript

Modules are used to structure the code in better way. Only Objects and functions exported by module can be used by outside world.
  • organize the code, variables, data
  • global scope, module scope, function scope and block scope
  • modules fix global variable problem
  • also function scoped variables fix the problem as well
  • below syntax (IIFE) can be used to create isolated scope/space/planet ( function() )();
  • So here js code in () gets executed but you can not access any props declared inside () from global space.
  • You can also create private variables using IIFE
  • thing you want to expose should be returned - called as revealing module pattern
  • jquery uses this pattern https://code.jquery.com/jquery-3.6.0.js

Problems with revealing module pattern

  • still global space is polluting but with 1 variable e.g. jQuery may get overridden
  • script dependency - order of the script tag also important

Solutions

  • CommonJS - used in nodejs - modules are loaded synchronously mainly used in server. exports and require keywords are used in commonJS. But they can not be used in browser directly. You will need bundler to use commonjs module in browser.
  • AMD modules are synchronous. AMD uses requirejs. Browserify converted requirjs modules to code that browser can understand
  • UMD - universal modules were invented to
  • ES6 - import and export keywords are used in ES6 modules.

commonjs modules

CommonJS module returns object - module.exports containing all things that it wants to make public Commonjs. Exports can be imported in 2 ways
  • using require - let os = require("os")
  • using import e.g import * as os2 from 'os'; import os from 'os';
Please note that when we import common js module in ES6 module, module.exports is treated as the default export.


function sum(a,b) {
  return a+b
  }
  
  let mul = function (a,b) {
      return a*b
  }
  
  module.exports = {  
      sum,
      mul
  }
  let X = require("./common-math.js")
  console.log(X.sum(2,3))
  console.log(X)

  
module.exports = {
  method: function() {},
  otherMethod: function() {},
};
//Or just:

exports.method = function() {};
exports.otherMethod = function() {};
//Then in the calling script:

const myModule = require('./myModule.js');
const method = myModule.method;
const otherMethod = myModule.otherMethod;
// OR:
const {method, otherMethod} = require('./myModule.js');
//commonjs
let os = require("os")

//ES6 - standard - make sure file extension is .mjs or type=module in package.json
import os from "os"

console.log(os.version())

ES6 modules

To make es6 modules work in browser, you need to serve the page via HTTP server and also use below syntax. Note the type is "module" it does not pollute global space

<script type="module"> </script>

ES6 module (asynchronous) export can be imported in only 1 way - using import

function sum(a,b) {
  return a+b
  }
  export {sum}
  import {sum} from "./es-math.mjs"
  console.log(sum(2,3))
  // os module exports object
  module.exports = {
    arch,
    cpus,
    endianness,
    freemem: getFreeMem,
    getPriority,
    homedir: getHomeDirectory,
    hostname: getHostname,
    loadavg,
    networkInterfaces,
    platform,
    release: getOSRelease,
    setPriority,
    tmpdir,
    totalmem: getTotalMem,
    type: getOSType,
    userInfo,
    uptime: getUptime,
    version: getOSVersion
  };
  
  let os = require("os")
  import * as os2 from 'os';
  import os from 'os';
  //You can only use import and export statements inside modules, not regular scripts.
  //otherwise you will get error saying can not use import outside module
  
  export { name, draw, reportArea, reportPerimeter };
  import { name, draw, reportArea, reportPerimeter } from './modules/square.js';

ES6 modules are asynchronous because we can use top level await keyword which is not possible with Nodejs.

ES6 modules can be of 2 types.
  • static - We can not load module conditionally
  • dynamic - We can load module conditionally. One disadvantage of dynamic module is that tree shaking (dead code elimination) is not possible.

 //dynamically loading module
 import('./mymodule.js')
   .then(obj => console.log("module loaded"))
   .catch(err => console.log("error occured"))

Resources

  • https://ui.dev/javascript-modules-iifes-commonjs-esmodules

Web development and Automation testing

solutions delivered!!