Modularization is simply making our source code split into logical units of independent, reusable code which become the building blocks of our application.
All the expressions like import, export, module.exports, etc. are the result of not having a native, standard way of modularizing in early stages. We will explore some of them.
Problems in the code
There are two major problems in this code. The code is obviously hard to read. The other major problem is the way of declaring variables and functions without thinking of the scope they are going to be in, the global scope or the window object.
All the variables and the functions are accessible via the window object as we can see in the above image. Those can be easily spoiled with variables and functions from another script source. What would be the result if we assigned null to the function playSong()? The functionality can’t be guaranteed in this case.
Although we could control the variable-creation in the global scope, still there is one variable residing in it, the variable keeping the module function. We can use Immediate Invoking Function Expressions or IIFE style to overcome this. Our function becomes anonymous and remains nothing in the global scope. The solution can be found here.
With this modification, we could completely reduce the usage of global scope. But the code is still containing more lines. If we could split the code into logical units or modules, the readability would be high. We can identify three units in this code. Those are App, Playlist and Song.
According to the previous solution, there should be three IIFEs. But the linkage among all three modules matters which is impossible to achieve after this separation. Even the order of these three modules declared in the HTML page matters. All of these approaches become unstable due to these reasons.
Module formats and loaders
As a solution to the problems mentioned above, module formats and loaders come into the picture. Module formats and loader have been suggested and implemented by various third parties. A module format can solve the linkage problem among the modules. There are unique syntax patterns used by various module formats to declare the dependencies. But these patterns are not a part of the language. Loaders are required to solve this problem.
AMD format can be loaded with a loader like require.js and CommonJS format can be loaded with a loader like system.js. Node environments have the native support of CommonJS format and no loaders are externally supplied. But the browser-based environments should be treated differently.
AMD module format
AMD format uses a keyword called define to express dependencies among modules. We will use the AMD format in our application. The module APP uses the other two modules as dependent modules and declared as follows. Note that the array of modules contains the file paths relative to the module app.js without extensions.
We will use require.js as the loader. We need to include it in our application. The distributed source can be downloaded from the GIT location or a package manager like npm. The solution can be found here.
The HTML page is modified to import require.js rather than our app.js. But we need to inform require.js where to begin, the entry point. This is given by the attribute data-main of the script tag.
CommonJS module format
CommonJS introduces a kind of import-export mechanism to declare dependencies. Every module is going to export something which would be available to be imported by another module with the variable module.exports. The keyword used for importing is require. We will use this format in our application as follows.
The configuration in the HTML page is as follows.
However, this style is commonly used in Node.js developments and the functionality of the loader is inbuilt.
We can export anything that should be available to be imported by another module with the keyword export. We can have a default export and any number of named exports per module. The new style is applied to our application as follows.
The HTML page is modified to include only the module app.js. But the way that the browser should treat this module should be given as an attribute to the script tag. The solution can be found here.
You can find the Git repository containing all of these concepts in the following link.
You can't perform that action at this time. You signed in with another tab or window. You signed out in another tab or…
Further reading …
There is a concept called bundlers. Webpack is an example. I would suggest you read on Transpilers, bundlers, Module formats and loaders more. We will discuss them further in the coming articles.