DEV Community

loading...
Cover image for ES6 Modules and how they work

ES6 Modules and how they work

Arsenii Gorushkin
Backend developer who wants to be Fullstack and DevOps Engineer
Updated on ・6 min read

If someone asked me, I would say modules are one of the most important parts of Javascript there is. You always want your code to look neat and clean, instead of being all messy and inside of a single file. This is what modules were made for. And today we are going to talk about their syntax, use, and functionality in ES6 version of Javascript.

Index

Last edit: 8/07/2021

Paths

Before we get to the imprting and exporting, I will first teach you about paths. In javascript, when import and or exproting, sometimes you would need to write a path to your modules. When writing a path, there are a few things you should know before starting to do it.

  • "/" - Separator between foulders/files
  • "./" - Directory you are located in (Used at the start of path)
  • "../" - Go to the parent directory, of the currently chosen one
  • "/" - Go to the home directory (Used at the start of path)
  • "~/" - Go to the user directory (Used at the start of path)

When writing, your path would look something like this
"./foulder1/foulder2/module.js"

Exports

Let's start learning about exports first, so that we can later apply our knowledge straight away on imports. Before we start, if you are using node, then put this in your package.json file

{
  "type": "module"
}
Enter fullscreen mode Exit fullscreen mode

This tells node to use ES6 syntax instead of commonjs. Now,let's start of with named exports:

Named Exports

Ok, so how would we export modules? We would use a keyword export as you might have guessed by now. Let's look at the example of the syntax

const constant = "string";

export { constant };
Enter fullscreen mode Exit fullscreen mode

This code would export constant after it's declaration, but what if we want to export it straight away? Then, as you might have guessed again, we would put an export keyword before const, same would be with function, let or anything else as you can see here

export const constant = "string";
Enter fullscreen mode Exit fullscreen mode

In both methods the constant is exported, but you use whether one you prefer. If you want to export multiple modules, then you would just put a coma after each module, like here:

const constant1 = "string";
const constant2 = "string";
const constant3 = "string";

export { constant1, constant2, constant3 };
Enter fullscreen mode Exit fullscreen mode

You are also able to change modules' name by using keyword as like shown below:

export { constant1 as constant };
Enter fullscreen mode Exit fullscreen mode

And yes, you do have to put named exports inside a curly bracket when exporting after declaration. Now, that we talked about named exports, let's move onto default exports.

Default Exports

Default exports are very similar to the named exports, they only differ a bit. Any one file can only contain one default export, and here is why: When exporting, you export by name, but why default export is good, is because it doesn't require to have a name. It exports a value without a name, meaning you can import it under any name in future without always having to remember it. And this is the reason you can only have 1 default export, it is because there couldn't be 2 different unnamed values exported at the same time, as it would be impossible to know which one you are reffering to when importing.

Now, let's look at the syntax for default exporting

const constant = "string";

export default constant;
Enter fullscreen mode Exit fullscreen mode

This is how we make an default export after it's declaration. As you can see, default export doesn't require curly brackets, so that's another plus. Now let's look at how to export during the declaration:

export default "string";
Enter fullscreen mode Exit fullscreen mode

As you can see, I didn't use any type definition keyword, it is because I'm exporting just a simple string, but in case you want to export something like a class, then remember this: Only expressions, functions, classes or arrow function are allowed. So, it means that if you try to export something like this:

export default const = "string";
Enter fullscreen mode Exit fullscreen mode

Then it will return a SyntaxError

Sometimes, when importing you might come around a problem of having long paths, and here is how you can fix it:

Aggregating Exports

Aggregation exports is when you take all of the exports from different files, and export them from one, and this is how:

Let's imagine you have different modules in different files like this:

export const module1 = () => {};
Enter fullscreen mode Exit fullscreen mode
export const module2 = () => {};
Enter fullscreen mode Exit fullscreen mode
export const module2 = () => {};
Enter fullscreen mode Exit fullscreen mode

They might be located very far away from each other, so you may not want to write long paths, and this is how you can do it. Create a file, where you will write with a syntax like this

export { module1 } from "./folder/folder2/folder3/module1.js";
export { module2 } from "./folder/folder2/folder3/module2.js";
export { module3 } from "./folder/folder2/folder3/module3.js";
Enter fullscreen mode Exit fullscreen mode

From this moment you would be able to import everything from one file where you have set up this system. But let's imagine you have 10000 modules for some reason all in one file, and you don't wan't to write out these curly braces, then this is for you:
In importing/export, you can use * to signify everything, so it would look something like this

export * from "./folder/folder2/millionModules.js";
Enter fullscreen mode Exit fullscreen mode

This will export all the modules from there for you. In case you want to rename one module you are exporting, you can do this by using as, as used before

export { module1 as module } from "./modules.js";
Enter fullscreen mode Exit fullscreen mode

You can also export everything as an object containing all the modules

export * as moduleObject from "./module.js";
Enter fullscreen mode Exit fullscreen mode

This is everything you need to know about aggrigartion. Now, let's move to the last part about exporting, await:

Await Exports

Await exports, as you might have guessed use keyword await, they can be used in case you want to export some data, for example from API response.
In the file where you are importing an await module, it will wait until the data is received in the module, and only then import it. Here is what syntax looks like

const data = await fetch("https://someurl.com");

export default await data;
Enter fullscreen mode Exit fullscreen mode

Before we move on, did you know that you can also mix exports like this

export { module1, module2, default as module3};
Enter fullscreen mode Exit fullscreen mode

This is about it for exports, now let's move onto imports

Imports

Before we start with imports, there are a few things I have to mention.
If you are using node, then you should be fine, but if you are using HTML, then you would first write a <sciprt> tag, and put type="module" inside, so that it recognizes it as a module. Another part, if you try to import modules using file:// URL, then you will run into CORS error, unless ran on http server. When importing module, then their value is unchangeable, even if they were declared as var or let. Modules also automatically use strict mode, so watch out for that.

Let's first talk about named module imports:

Named Imports

When importing named values, as well as in exporting you would need to use curly braces around the module(s) that you want to import. Like with export, import uses import keyword. Now let's look at how it works.

import { module1 } from "./foulder/module.js";
Enter fullscreen mode Exit fullscreen mode

You can also import modules under their own namespaces:

import { module1 as m1, module2 as m2 } from "./foulder/modules.js";
Enter fullscreen mode Exit fullscreen mode

You can also use namespaces:

import * as modules from "./modules.js
Enter fullscreen mode Exit fullscreen mode

This is basically it for named imports, now let's move onto default ones.

Default Imports

Default imports, as seen in export example, are basically the same as named ones, they just don't require curly brackets.

import module from "./module.js";
Enter fullscreen mode Exit fullscreen mode

This is as simple as that, now let's move onto dynamic imports, a very interesting feature in JS.

Dynamic Imports

Dynamic impports are a function, that can be called anywhere in the code. This function is asynchronous, meaning that it requires await keyword or a then() method, as it is a promise. The type of data it returns is like this:

{
  default: defaultMethod,
  module1: module1,
  module2: module2,
}
Enter fullscreen mode Exit fullscreen mode

import() takes in one parameter, path, and is used something like that.

import("./modules.js").then((modules) => {
  modules.module1();
});
Enter fullscreen mode Exit fullscreen mode

This post basically has now covered everything you might have wanted to know about ES6 imports, if there is something I either didn't say or got wrong, feel free to point it out in the comment, would love to get some feedback.

If you enjoyed the post, then please react, share and or follow for more interesting posts like that. However, if you didn't like it, then tell what you didn't like, and I'll try to fix it.

See you in the next post!

agorushkin image

Discussion (13)

Collapse
ryanguitar profile image
Ryan Els

Nice article. I think the use of aggregating modules is also worth a mention. I have found it very useful in a project I am busy with. You can get more info in the mozilla docs at developer.mozilla.org/en-US/docs/W... . When it comes to variables in es modules it is important to note that imported variables are read-only and need to be updated on the export file.

Collapse
agorushkin profile image
Arsenii Gorushkin Author

Thank you for taking your time and leaving a feedback! I will check out the source that you sent to me (Thanks for it). Whenever I write these, I write from my own experience. And as I don't really have a "checklist" of sorts with every single feature, sometimes it happens that I forget to mention one or another thing. But once again, thank you for your feedback!

Collapse
martixy profile image
Martin Ninov

You covered all the syntax of es6 modules and none of the functionality. Very little of how they actually work.

  • Modules are automatically strict.
  • Modules create live bindings.
  • Modules enforce CORS.

etc.

Collapse
agorushkin profile image
Arsenii Gorushkin Author

Sorry to disappoint you. When I started writing I kind of wrote it for myself, didn't expect anyone to see it.

Collapse
jonrandy profile image
Jon Randy

NPM imports will not work unless you're using a bundler

Collapse
agorushkin profile image
Arsenii Gorushkin Author

That's a good point. Sorry if I did happen to make some mistakes

Collapse
jonrandy profile image
Jon Randy • Edited

Luckily though, this is easy to rectify by importing the NPM modules from Skypack

Thread Thread
agorushkin profile image
Arsenii Gorushkin Author

When making, I just kind of had an idea in mind that I was going to make it for node. I was just pretty sure that node natively supported NPM, so my bad on that part of not doing good enough of research

Collapse
devtechk profile image
Devtechk • Edited

Hi! can you describe this mixing import, “ import defaultModule, { module1 as module, module2 } from "source/somePath/module.js";” as you wrote in your post? Thank you!

Collapse
agorushkin profile image
Arsenii Gorushkin Author

defaultModule would be a default export that we did in another file, modules in curly brackets would be named modules, for module1 we just change the name, while for module2 we import it as it is

Collapse
stasyushkov profile image
stas-yushkov

Nice tutorial) Thx.
Can you talk more about Dynamic Imports?

Collapse
agorushkin profile image
Arsenii Gorushkin Author

Yes, I have just edited it due to some requests, hope it will be easier for you to understand :D

Collapse
alimbolar profile image
Alim Bolar

Just what I needed!!.. thanks.. it really helps..