Modules

JavaScript modules are not new. In fact, there were have been libraries that support modules for some time now. ES6, however, offers built-in modules. Traditionally, JavaScript's major use was on browsers, where most of the JavaScript code was either embedded or small enough to manage without much trouble. Things have changed. JavaScript projects are now on a massive scale. Without an efficient system of spreading the code into files and directories, managing code becomes a nightmare.

ES6 modules are files. One module per file and one file per module. There is no module keyword. Whatever code you write in the module file is local to the module unless you export it. You may have a bunch of functions in a module, and you want to export only a few of them. You can export module functionality in a couple of ways.

The first way is to use the export keyword. You can export any top-level function, class, var, let, or const.

The following example shows a module inside server.js where we export a function, a class, and a const. We don't export the processConfig() function, and any file importing this module won't be able to access the unexported function:

    //----------------server.js--------------------- 
    export const port = 8080; 
    export function startServer() { 
      //...start server 
    } 
    export class Config { 
      //... 
    } 
    function processConfig() { 
      //... 
    } 

Any code that has access to server.js can import the exported functionality:

    //--------------app.js---------------------------- 
    import {Config, startServer} from 'server' 
    startServer(port); 

In this case, another JavaScript file is importing Config and startServer from the server module (with the corresponding JavaScript file server.js, we drop the file extension).

You can also import everything that was exported from the module:

    import * from 'server' 

If you have only one thing to export, you can use the default export syntax. Consider the following piece of code as an example:

    //----------------server.js--------------------- 
    export default class { 
      //... 
    } 
    //--------------app.js---------------------------- 
    import Server from 'server'; 
    const s = new Server(); 

In this example, we will keep the class anonymous as we can use the module name itself as the reference outside.

Before ES6 modules, external libraries supported several approaches to modules. They established fairly good guidelines/styles for ES6 to follow. The following style is followed by ES6:

  • Modules are singletons. A module is imported only once, even if you try to import it several times in your code.
  • Variable, functions, and other type of declarations are local to the module. Only declarations marked with export are available outside the module for import.
  • Modules can import from other modules. The following are the three options for referring to other modules:
    • You can use relative paths ("../lib/server"); these paths are resolved relatively to the file importing the module. For example, if you are importing the module from <project_path>/src/app.js, and the module file is located at <project_path>/lib/server.js, you will need to provide a path relative to the app.js - ../lib/server in this case.
    • Absolute paths can also point to the module file directly.
    • You can drop the file .js extension while importing the module.

Before we go into more details of the ES6 module system, we need to understand how ES5 supported them via external libraries. ES5 has two non-compatible module systems, which are as follows:

  • CommonJS: This is the dominant standard as Node.js adopted it
  • AMD (Asynchronous Module Definition): This is slightly more complicated than CommonJS and designed for asynchronous module loading, and targeted toward browsers

ES6 modules were aimed to be easy to use for engineers coming from any of these systems.

Export lists

Instead of tagging each exported function or class from your module with the export keyword, you can write a single list of all the things you want to export from the module, which are as follows:

    export {port, startServer, Config}; 
    const port = 8080; 
    function startServer() { 
      //...start server 
    } 
    class Config { 
      //... 
    } 
    function processConfig() { 
      //... 
    } 

The first line of the module is the list of exports. You can have multiple export lists in the module file and the list can appear anywhere in the file. You can also have a mix of export list and export declarations in the same module file, but you can export one name only once.

In a large project, there are cases when you encounter name conflicts. Suppose you import two modules, and both of them export a function with the same name. In such cases, you can rename the imports as follows:

    import {trunc as StringLib} from "../lib/string.js" 
    import {trunc as MathLib} from "../lib/math.js" 

Here, both the imported modules exported a name, trunc, and hence created a conflict of names. We can alias them to resolve this conflict.

You can do the renaming while exporting as well, which is as follows:

    function v() {} 
    function v2() {} 
    export { 
      v as functionV(), 
      v2 as functionV2(), 
      v2 as functionLatest() 
    } 

If you are already using ES5 module systems, ES6 modules may look redundant. However, it was very important for the language to have support for such an important feature. ES6 module syntax is also standardized and more compact than the other alternatives.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.19.251