Import, Exports, and Require(it) Too!
Tags: javascript, node, beginners, codenewbie
Published: 2019-10-20 20:59:22

We've all ordered something from the internet right? Whether the shipping was domestic or international, at one point in time you've more than likely had to wait a few days for something to come in the mail from somewhere nearby, or more often, from some far away place where the shipping cost was $20+.

We could probably find the same item domestically of course, and it could even be better quality, but the caveat is usually that while domestic shipping takes less time and costs less, the price of the item is typically more expensive than an imported item.

Once we've reached this point in our on-line shopping cart, the age old internal battle of wits begins:

 *"Do I pay the local cost, and save on wait time but pay more for the item? Or do I pay the international costs and save on the overall expense but spend more time waiting on it?"*

It usually boils down to one very simple solution: 
_However we're feeling at the time!_ ¯\_(ツ)_/¯

We know we're going to pay either way, so it truly just depends on what we want, how soon we want it, and how much we're willing to pay to get it, right?

Well, that thought process is really the same when using ES5's <i>module.exports/exports</i> and <i>require( )</i>, and the update to those methods in ES6 to <i>import from</i> and <i>exports</i>.

I recently did a presentation on this subject and the details of the specifics of this topic are broad and vary, *but*, there are definitely some very helpful, solid principles to remember when importing and exporting...well, there is really just one MAIN principle to remember:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/xba95htv6wc3gqg29f1i.png)

That's it! As long as you stick with a singular concept and only use *module.exports/require() _OR_  import/exports*, you won't get tripped up in code conflicts.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/guolyyfws0ti1jt8v2zq.gif)


##Imports, Exports, & Conflict Resolution##
The idea behind importing and exporting was an ES5 collaboration between CommonJS & Nodejs as a resolution to various issues software developers were facing when building out modular programs. 

Often times, the DRY principle was broken to use the same functions in different parts of the program, and
of course, before long, this became increasingly problematic. Luckily, CJS and Nodejs came
up with a simple solution: Confine these declarations in their own file, then, *require* the desired
code snippets for use in another.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/2kxnc30pscouiscx2d3e.gif)

Now, instead of rewriting the same lines of code over and over and possibly overwriting previously declared variables, the same piece of code could be used multiple places throughout a program without any additional conflicts! Programmers rejoice!

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/53vrbl4s513vndafyqk7.gif)

###module.exports / exports###
*Module.exports* or sometimes just *exports* is a special default object that comes built-in to Node. This special object is used to ease module creation and encapsulation, the result of which is cleaner, more organized code and access to specific properties that would not be typically available due to the individual scope of each module in a program.

Exports can be any data type and exported in a variety of ways, such as directly as an object, a named variable, and even dynamically as a function. Now, with just a little effort, we can get the code bits we want out of confinement, and drop sprinkle them into the new scopes where we want them, *without* causing new conflicts in the program.


```javascript
seinfeld.js

module.exports = {  
   firstName: 'Elaine',
   lastName: 'Benes'
}

//exports is just a method on the special module object
exports.SoupMessage = 'No soup for you!';

module.exports = function(cerealName){
   console.log('I love ' + cerealName +'!');
}
```

###require( )###
It's just as easy to require pieces of code in separate files as it is to export them. By using *require( )*, code snippets can jump safely out of their scope and brought into another. Not only can an individual's code be exported and required, but so can package files.

```javascript
seinfeld.js

const crpyto = require('crypto');
const axios = require('axios');
const faces = require('cool-ascii-faces');
```
These snippets are loaded via their file paths or package names and can also be done so in a variety of ways:
  
```javascript
showAboutNothing.js


const Elaine = require('./seinfeld');

//grab a utility library while you're at it
const util = require('underscore');

//as a deconstructed object or array
const { George, Jerry} = require('./seinfeld');
const [ Kramer, Elaine ] = require('./seinfeld');
```
###import from / export###
Following the success of the module.exports object and require method, this process was kept in, and updated with the release of EcmaScript2015(ES6). 

Additionally, in ES5 syntax the file is evaluated from top to bottom. Once the interpreter sees the call to require( ), it jumps to that file to retrieve the exports, and then jumps back to the current file. 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/tvgjo68v7wx2qr06vp1q.gif)

This can cause a lag in the program and was updated in ES6. Now, the program is read before it is evaluated and is immediately prepared to run, optimizing the program's overall performance.

The ES6 update also dropped the use of the keyword 'module' and adjusted the command to just _export_. Functions, Objects, and primitive data types are still available to be developers as Named exports, which include 0 or more per module, as Default exports, including only one export per module, or as Hybrid exports, which is a combination of both.
 
```javascript
seinfeld.js

//as deconstructed object
export { George, Jerry } = theGuys;

//a regular object
export default function ({
    firstName: 'Elaine',
    lastName: 'Benes'
};

//variable
export const seinFeld = aShowAboutNothing();

//function
export function helloNeighbor(){
    console.log('KRAMER!');
//classes
export class VandelayInd{...}

//via list and alias

export { george, jerry, elaine, kramer };
};

//aliases help to avoid naming conflicts
export {jason as george, julia as elaine};

```

Keeping in the same spirit of development ease, importing from a file is just as easy as it was to require( ) a file. Properties can also be imported dynamically, individually or in groups.

```javascript

//it's as easy as letting the interpreter know where to import from

import { getVandelayEmployees } from'/modules/seinfeld.js';

//importing can be done dynamically as well

import('/modules/vandelay.js')
.then((jobTitle) => {
    console.log(`I'm the ${jobTitle} at Vandelay Industries`);
});
```

#In Conclusion#
Whether we use *module.exports* and *require* or *import from* and *exports*, developers have the peace of mind of knowing that whatever our choice, the possibility of conflicts is reduced exponentially by using these helpful commands in our code. By sticking to the "One" rule and only using one version at a time, projects will be cleaner, more modular, and expertly organized.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/gorc0scmxkhki514lxlg.gif)

What more could a developer ask for?

I  advise you to do some deep exploration in the MDN docs for a wealth of additional information on this topic, as it is incredibly broad, and one syntax may better suit your needs than the other depending on your project.

Now get out there and _export/import_ something!

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/nhzbatf7g77cplhzeuz3.gif)


Thanks for reading!
"✌(-‿-)✌"