For a long time, JavaScript didn’t have any concept of modules. It didn’t have the ability to say that one file was dependent on another file, and no way of exporting values from one file to another.

JavaScript files had to be included with <script> tags, and they had to be in the correct order to prevent them from interfering with one another. It was unclear which files were dependent on other files, and what those depencencies were.

With a long list of <script> tags, your code could quickly get messy and turn into a dependency nightmare.

Some people went ahead and created their own solutions to this problem, such as commonJS. If you’ve used Node.js and the require() function, then you've seen commonJS in action.

In the newest version of JavaScript (called ES6), JavaScript has two new features to do this natively.

They are called, appropriately, export and import.

No web browser supports these features yet, so to try them out you need a JavaScript compiler such as Babel, which will convert your ES6 JavaScript into the kind of JavaScript that your web browser understands.

Now let’s take a look at some examples.

Exporting

Exporting named values

When working with modules, nothing is exported by default. We need to explicitly say which files we want to export.

Suppose we have this file:

// pets.js

var dog = {
  name: 'Milo'
  age: 3
};

var cat = {
  name: 'Snowball'
  age: 2
};

var numberOfPets = 2;

function meow() {
  console.log('Meow chicka meow meow.');
}

function woof() {
 console.log('Woof woof!');
}

If we want to export specific values from our code, we can wrap them in curly braces after the export keyword, separating multiple values with a comma:

export { dog, cat };

If we want to call the values something else, we can specify an alias name after the original name:

export { dog as milo };

We can also declare and export a value at the same time:

export var dog = { name: 'Milo' age: 3 };

Exporting the default value

By using the default keyword, we can specify the value that will be exported as the main or default value. We can use this keyword only once per module.

We can export JavaScript expressions directly:

export default { name: 'Snowball', age: 2 }

Or by specifying a previously declared value:

export { cat as default };

However, we can’t export a variable declaration as a default:

export default var catOwner = 'John' // invalid

In addition to JavaScript expressions, we can also export functions or ES6 classes:

export default function meow() {
  console.log('Meow chicka meow meow.');
}

Importing

Importing named values

We can easily import only the values we need from another file. The .js extension can usually be ommited:

import { dog, cat } from "pets";

We can import the value with another name:

import { dog as hound } from "pets";

And we can import named values together with the default value:

import dog, { numberOfPets } from "pets";

Importing the default value

To import the default value from a file, we just specify a name of our choosing, and the default value will be imported with that name.

import cat from "pets";

Importing everything

If we want to import everything that is being exported from another file, we write an asterisk and a name. All the values will be put into an object that we can use.

import * as ourPets from "pets";

console.log(ourPets.numberOfPets) // will print out 2

Be sure to check out the documentation on import and export over at the Mozilla Developer Network if you want more information.