Image credit: Jsmodular

Javascript modular history

Image credit: Jsmodular

Javascript modular history

Javascript has been dramatically used in front-end and back-end compared to the time when it was invented. When the time it was invented, it supposes to be a joy programming language, doing some simple interactions between browser. However, since the ubiquitous usage of browser. Javascript has become the most important language in the web ever.

Unlike language like Java and Python. Javascript does not have a module loader initially. Here are several ways to load module from past to present.

  • Classic
  • RequireJs(AMD)
  • CommonJs
  • ES6

Old Fashion

In the past, when javascript was still not heavily used. There are probably only several js files. It’s easy to manipulate it manually. Here is an example.

<script src="js/jquery.js"></script>
<script src="js/point.js"></script>
<script src="js/line.js"></script>
<script src="js/polygon.js"></script>
<script src="js/main.js"></script>

Since there are many modules/files rely on jQuery, if you put jQuery script tag at the end of this file, the modules which rely on jQuery library will not work just like building a house you need build basement first, then each level up or like draw an image, you need point, line and polygon first. The disadvantage of this kind of module loader is you have always take care of them, once you put them in a wrong order, the console will yell. If your application is small, that’s okey, you can well manipulate them manually. Suppose this is a big project which involves many developers, to control the dependency manually will be a nightmare.

RequireJs

Here is a paragraph I get from requirejs homepage.

RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node. Using a modular script loader like RequireJS will improve the speed and quality of your code.

As this quote mentioned requirejs is a module loader, it can be used both in front-end and back-end. It’s quite simple to use it. Suppose you have a document file tree like this.

- project_directory/
  - index.html
  - scripts/
    - main.js
    - utils.js
      - someutils.js

The main.js is your main entry point, every code should be traced back to main.js, unlike old fashion, you don’t have to create many script tags. All you need to do is like following.

<!DOCTYPE html>
<html>
    <head>
        <title>My Sample Project</title>
        <!-- data-main attribute tells require.js to load
             scripts/main.js after require.js loads. -->
        <script data-main="scripts/main" src="scripts/require.js"></script>
    </head>
    <body>
        <h1>My Sample Project</h1>
    </body>
</html>

The attribute data-main defines your main entry point, the src attribute will load the require.js modular loader first, then run main.js

requirejs(["utils/someutils.js"], function(util) {
    //This function is called when scripts/helper/util.js is loaded.
    //If util.js calls define(), then this function is not fired until
    //util's dependencies have loaded, and the util argument will hold
    //the module value for "helper/util".
});

Inside main.js you could load all dependencies in the first argument of function requirejs and this argument will be passed as the first argument of the callback function. Simply to say util is the alias of “utils/someutils.js”

RequireJs also provide config functionality. Suppose you want to use jQuery. Inside your main.js you could add following code

requirejs.config({
    baseUrl: 'utils/lib',
    paths: {
        // the left side is the module ID,
        // the right side is the path to
        // the jQuery file, relative to baseUrl.
        // Also, the path should NOT include
        // the '.js' file extension. This example
        // is using jQuery 1.9.0 located at
        // utils/lib/jquery-1.9.0.js, relative to
        // the HTML page.
        jquery: 'jquery-1.9.0'
    }
});

Here the baseUrl can make things much easier. Every time you want to use jQuery as a dependency, you don’t have to manually type the full path. Here is the example, suppose you want to create you own modular called addTitle.js

define(["jquery"], function($){
  // create your own module here
  // can use $ sign as we normally use jQuery
});

CommonJs

CommonJs is used in backend nodeJs. It’s the default module loader for nodeJs. It has two main systems: require/import and export.

const myModule = require('path/to/mymodule');
// if this is a class, it's really to be used
const myObject = new myModule();

Some languages like Python and Java, you don’t explicitly to export your class or methods. However, in commonJs your have to explicitly to export your class and methods to be used

// one way to export
module.exports = class Dog{
  constructor(name){
    this.name = name;
  }
  
  bark(){
    console.log("Woooo");
  }
};

// or your can create class first, then export it
class Dog{
  // define your class first
}
module.exports = Dog;

// only want to export certain methods
module.exports.add = (a,b)=> a + b;

I think the grammar of commonJs is more natural and it’s easier to understand

ES6/ES2015

ES6 is the new standard for javascript. Unfortunately, it’s not supported by modern browsers now. It has added many new features and syntactic sugar. These new features make developers who come from different language background feel easy to learn javascript. In order to use it, you have to use Babel to transpile it to current browsers supported javascript code.

// this is your partical.js module
export default class Partical{
  // here is your implementation
}

// this is your personalizedmath.js module
export function square(x) {
    return x * x;
}

export function pow3(x){
  return x**3
}

// this is your main.js module
// since this is not default export, brakets is required
import { square, pow3 } from 'lib/personalizemath';
// since this is default export, there is no need to
// add brakets, and you can rename to what name you want
import Partical from 'lib/partical'
console.log(square(11)); // -> 121
console.log(pow3(2)); // -> 8
let myPartical = new Partical();

ES6 adds many features, it worths to study. Here is a short list for ES6 features

  • Arrow function (a,b)=> a+b
  • default parameter const myfunc = function(height=50, color='red'){...}
  • spread operator const listA = [1,2,3]; const listB = ['A', 'B', ...listA] // listB -> 'A', 'B', 1, 2, 3

Reference

Avatar
Terry Pan
Student of Data Science

My research interests include Machine Learning, Data Science, Information Security and Software Engineering. I like to think like a engineer to tackle real world problems.

comments powered by Disqus