Modules

When creating large applications and using web frameworks like NodeJS you need to understand modules, modules allow you to break up code into specific parts, generally those parts are linked for example you might have a couple of modules to deal with the database.

Module Pattern

The idea behind the module pattern is to break code into logical pieces which are encapsulated from the rest of code, you also have the ability to only expose what needs to be exposed, these logical pieces can be changed and tested easily. The most benefit when you have module system is how to handle dependencies, one module depending on another, this is comes in handy when you use 3rd party modules, modules have a unique identifier so that you can retrieve specific dependant modules. When using a framework like NodeJS they use a packager manager called npm to handle external modules and their dependencies. In plain old Javascript you have to order the script element so that you load your modules in the correct order.

From ES6 modules had a full specification that made things simple in terms of the module loader and the browsers support, it took the best of the old AMD and CommonJS loaders in previous Javascript versions.

You can add a script tag called type="module" to associate the code as a module, instead of executing it

Using script tag and modules
<script type="module">
    // module code
</script>

<script type="module" src="path/to/myModule.js"></script>
script ordering
// Executes 2nd
<script type="module"></script>

// Executes 3rd
<script type="module"></script>

// Executes 1st
<script></script>

Newer browsers will load the entire dependency graph from the top-level module and will do this asynchronously, once the pieces start to come over the network the browser will parse their contents, identify their dependencies and then send out more requests for those dependencies this continue until the entire dependency graph is resolved. Once this has been completed the application can begin to load. You have to be aware that the more dependencies the longer it will take to rsolve and decrease performance. Below is a list of all the features ES6 uses

Module Export and Import

The exports keyword is used to export parts of a module which allows other code or modules access, there are two types of exports in ES6 modules, exports and default exports.

Export examples
export const foo = 'foo';          // one liner, you can export multiple exports
    
const foo = 'foo';
const bar = 'bar';
export { foo, bar };                    // you can export later in the code
export { foo as myFoo, bar };           // export using a different name
Default export examples
const foo = 'foo';
export default foo;

const foo = 'foo';
const bar = 'bar';
export { foo as default, bar };


Note: you can only have one default export, A default export can be a function, a class, an object or anything else.

Now that we know how to export our modules lets see how we import one, using the import keyword which should reside at the top of the file (they are hoisted otherwise) you can import a specific module, you can either use a absolute path or use a relative path

You may want to check out the application you are using with Javascript as for example NodeJS does need some tweaking to get the export/import working, also when using the default flag you may or may not need curly braces this depends on the Javascript application (like NodeJS) you are using.

Import examples
import { foo } from './fooModule.js';                        // relative path
import { bar } from '/opt/js/modules/barModule.js';          // absolute path

// bulk load from the module and use your own custom identifier Foo in this case
import foo, * as Foo './foo.js';                             
consol.log(Foo.foo);

// perform explicit imports
import { foo, bar, baz as myBaz } from './foo.js';
console.log(foo);
console.log(myBaz);

// if the module is using default
import { default as foo, bar, baz } from './foo.js';