Modular programming with ES6

Features of ES6 modules

es6 module

With the new version of JavaScript ES6 comes integrated support for modular programming.

  • Supports modules placed in files – one module per file
  • Modules are unique instances, each module is executed only once (singleton model).
  • ES6 modules can work both synchronously and asynchronously.
  • Supports “cyclic dependencies”.
  • The syntax is even more compact than CommonJS
  • ES modules have a static structure. Since the module structure is immutable, it is often enough to look at the code and figure out what is being imported where. This is not the case with a dynamic structure, where the code often needs to be executed to see what is being imported. Possible errors can also be found at the time of compilation (with the module bundler), because all actions related to the import and export of modules are determined at that moment.
  • All imported elements are immutable from the importing module. Any operation to assign a value to an imported element would cause an error (TypeError).
  • ES6 does not make a copy of a property but shares a link to that property. This is true even for sharing primitive properties (“number” or “string”). In the following example, we see that if the parent module changes the value of the shared property (the change was made by a method from the parent module!), the module that imported that property “sees” that change.
    EXAMPLE
    budget.js

    main.js

    We import all the elements that were exported from the module “proracun.js”

    If the variable “counter” was used now in some “third” module, it would have the value 2.

Export module

Standard export

Standard exporting is achieved by placing a reserved word in front of the variable (function) declaration:

Named export

Named (named) exporting is the syntax with which we define the elements for export at the end of the module. The name came from the fact that their names are used to define the exported elements.

Default export

It is recommended that when exporting a module, define a part of the module that is exported by default. The default export is defined with the revised word default. Only one default export is allowed per module. The exported part is used in another module under the name “default”.

The default export can also be defined with a “named form” with the addition of the keyword “as”:

NOTE: this syntax is not allowed (classic example of ES6 syntax inconsistency):

Re-exporting

Re-exporting means exporting from a non-native module.

Recommendations

If the module has quite a number of “scattered” elements that are exported, it is recommended to define the API clearly and clearly at the top of the module, as in the following example:

Module import

Features

  • The variable or function declaration is raised to the beginning of the domain during the compilation phase (hoisting). Therefore, calling the function in the following example will not throw an error:
  • All imported elements are immutable from the importing module. Each operation of assigning a value towithin the module (which imports) would cause an error (TypeError). However, in the case of an object, we can change it indirectly:
    EXAMPLE
    lib.js

    main.js

  • It is not allowed to use variables in the import statement. Modules are static, so the import must not depend on something obtained at runtime. So the syntax in the following example is incorrect and returns an error:

  • Conditional loading of modules with only ES6 syntax is not possible. The reason for this is that the “import” statement must always be “top level”, which is not achieved by indenting it inside an if loop. Therefore, for such a case, a programmable loader must be used – System.JS, which would have some additional script:

Named import of modules (named import)

Import default elements

Importing default values is done by simply calling the module name or calling it by name.

Importing the entire module (Import namespace object)

We use global import if we want to load all exported elements of a module in one command. Namespace import requires the syntax * as.

After which all elements from module “foo” are available in the module under the “new” name “bar”:

If there were default values defined in the exported module, after importing the entire namespace, it is called with “default”:

EXAMPLE
budget.js

main.js

Journeys to production

Since the ES6 syntax is not yet sufficiently supported in browsers, it is necessary to carry out certain preparations before putting it into production:

  • Select transpiler (Babel Typescript…)
  • Selecting the format we want to convert to during transpilation (AMD or CommonJS).
  • Transpiling code
  • Choice of dependency manager “module loader” (require.js or SystemJS) or “module bundler” (Browswerify or Webpack).
  • Integration of “dependencies manager”

Although this road is quite thorny, it is considered that ES6 modules are the future and will over time supplant all formats used so far, and even CommonJS on the server side.