---
tags:
  - node-js
---

# Modules

> Modules are partitioned files where we define our variables and functions.
> Values defined in modules are scoped to that specific module, constituting a
> unique name space. This avoids name clashes in large programs.

- Every file in a Node application is considered a module.

- The variables and methods in a module are equivalent to `private` properties
  and methods in object-oriented programming.

- If you wish to use a function or variable defined in a module outside of its
  modular container you need to explicitly export it and make it public.

## Structure of a module

Node keeps an internal record of the properties of a module. To see this we can
log the property `module` to the console.

```js
// index.js
console.log(module);
```

This gives us:

```plaintext
Module {
 id: '.',
 path: '/home/thomas/repos/node-learning',
 exports: {},
 filename: '/home/thomas/repos/node-learning/index.js',
 loaded: false,
 children: [],
 paths: [
   '/home/thomas/repos/node-learning/node_modules',
   '/home/thomas/repos/node_modules',
   '/home/thomas/node_modules',
   '/home/node_modules',
   '/node_modules'
 ]
}
```

## Exports

- Whenever we export a property or method from a module we are directly
  targeting the `exports` property of the module object.
- Once we add exports to a file they will be displayed under that property of
  the module object.
- We can export the entire module itself as the export (typically used when the
  module is a single function or class) or individual properties.

### Exporting a whole module

_The example below is a module file that consists in a single function_

```js
module.exports = function (...params) {
  // function body
};
```

Note the module is unnamed. We would name it when we import:

```js
const myFunction = require("./filenme");
```

### Exporting sub-components from a module

In the example below we export a variable and function from the same module.
Note only those values prefixed with `exports` are exported.

```js
exports.myFunc = (...params) => {
  // function bod[]()y
};

exports.aVar = 321.3;

var nonExportedVar = true;
```

This time the exports are already name so we would import with the following:

```js
const { myFunc, aVar } = require("./filename");
```

We can also do the exporting at the bottom when the individual components are
named:

```js
const myNamedFunc = (val) => {
  return val + 1;
};

function anotherNamedFunc(val) {
  return val * 2;
}

// This time we export at the bottom
exports.myNamedFunc = myNamedFunc;
exports.differentName = anotherNamedFunc; // We can use different names

// Or we could export them together
module.exports = { myNamedFunc, anotherNamedFunc };
```

The import is the same:

```js
const { myNamedFunc, anotherNamedFunc } = require("./modules/multiExports");
```

## Structuring modules

The techniques above are useful to know but generally you would want to enforce
a stricter structure than a mix of exported and private values in the one file.
The best way to do this is with a single default export.

Here the thing exported could be a composite function or an object that
basically acts like a class with methods and properties.

_Export a composite single function_

```js

module.exports = () => {
	foo() {...}
	bar() {...}
}
```

_Export an object_

```js

module.exports = {
	foo : () => {...},
    bar: () => {...}
}
```

**Both of these structures would be referred to in the same way when importing
and using them.**

Or you could export an actual class as the default. This is practically the same
as the two above other than that you would have to use `new` to initiate an
instance of the class.

```js
export default class {
  foo() {}
  bar() {}
}
```

Every method and property within the export will be public by default, whether
it is an object, class or function. If you wanted to keep certain
methods/properties private, the best approach is to define them as variables and
functions within the module file but outside of the `export` block.
