Professional Documents
Culture Documents
ES6 JavaScript Modules
ES6 JavaScript Modules
Sign up
JavaScript
One of my least favorite things about JavaScript is having tons of script tags in my HTML that all
depend on one another since it is so easy to accidentally break the code if they are put in the
HTML in the wrong order. It also makes it hard to work with your code since all the variables
from all your files are global and shared so accidentally overwriting variables between files is
really easy to do. This is why when JavaScript introduced ES6 modules I instantly fell in love
because it solves all these problems and more.
If you prefer to learn visually, check out the video version of this article.
Privacy - Terms
https://blog.webdevsimplified.com/2021-11/es6-modules/ 1/8
06/09/2022, 10:36 ES6 JavaScript Modules
// User.js
let userCount = 0
class User {
constructor(name, age) {
this.name = name
this.age = age
userCount++
function printName(user) {
function printAge(user) {
// script.js
printName(user)
printAge(user)
<script src="User.js"></script>
<script src="script.js"></script>
As you can see from the above code our User.js file defines our User class and the functions for
interacting with the user. Then in our script.js file we are accessing the User class and those
methods. The reason we are able to access that class and methods is because we added the
script tag for loading the User.js file above the script tag that loads our script.js file.
Privacy - Terms
https://blog.webdevsimplified.com/2021-11/es6-modules/ 2/8
06/09/2022, 10:36 ES6 JavaScript Modules
This has the problem, though, where we need to ensure our User.js file always loads before our
script.js file and also the User class and functions are global variables so if we have another file
that we import somewhere that defines a printName function it will override the printName
function from the User.js file.
To fix this problem we can turn to ES6 modules. ES6 modules allow us to export specific
information from one file and then import it into another file. Let's look at a quick example of
exporting data from our User.js file.
Exporting
// User.js
let userCount = 0
class User {
constructor(name, age) {
this.name = name
this.age = age
userCount++
function printName(user) {
function printAge(user) {
export printName
export printAge
At the bottom of the User.js file we added 3 lines to declare our exports. As you can see we
have one default export and then two non-default exports which are called named exports.
With ES6 modules you can have as many named exports as you want, but you can have at most
one default export. Now defining your exports on their own line like this does work, but you can
instead define your exports on the same line you define your functions/classes which in my
opinion is much easier to read. Privacy - Terms
https://blog.webdevsimplified.com/2021-11/es6-modules/ 3/8
06/09/2022, 10:36 ES6 JavaScript Modules
// User.js
let userCount = 0
constructor(name, age) {
this.name = name
this.age = age
userCount++
This has the same effect as defining the exports on their own line, but makes it more clear what
code is being exported and what code is not being exported. For example you can see that we
are not exporting the userCount variable which means that no code outside the User.js file can
access that variable. This means that we can have a private variable that can only be accessed
in the file it is defined which was something that was difficult and clunky to do without ES6
modules.
Importing
// script.js
printName(user)
printAge(user)
Privacy - Terms
https://blog.webdevsimplified.com/2021-11/es6-modules/ 4/8
06/09/2022, 10:36 ES6 JavaScript Modules
The only difference is the first line of this file where we have the import keyword. The way
importing works is you put the import keyword followed by the default import if you have a
default export. Then you put a comma after the default export and define all named exports
inside curly braces. Finally, you end the statement with the from keyword followed by the path
to the file. The file path for the imported file is relative to the file doing the importing and must
have ./ at the start of the path.
Let's look at a few examples of what this code would look like for different scenarios
Renaming Imports
It is common to need to rename the functions/classes/variables you import from another file
for example if you already have another variable that has the same name or you want to use a
name that is more clear. Let's look at examples of how to rename both the default export and
named exports.
Renaming the default export is incredibly easy since you just need to do a normal import, but
put whatever name you want where you put the default export.
In this example we renamed the default export to Person from the name User . The reason
that we can do this is because you can only ever have one default export so JavaScript is smart
Privacy - Terms
https://blog.webdevsimplified.com/2021-11/es6-modules/ 5/8
06/09/2022, 10:36 ES6 JavaScript Modules
enough to know whatever name you give the default export will correspond to the only default
export from the file.
Renaming named exports is a bit more difficult since JavaScript uses the name of the export to
know which export you are importing. This is why when you rename a named export you need
to put the name of the export followed by the keyword as and then the new name you want to
use.
// script.js
printUserName(user)
HTML Changes
If you have been following along with this tutorial you may have noticed that you are getting an
error when trying to use this new module syntax. The reason for this error is because by default
the browser does not know how to handle module imports. You need to specifically define in
the HTML that you are using modules.
By setting the type="module" attribute in JS we are telling the browser this code uses
modules. You will also notice we don't need to include a script tag for the User.js file since the
import of that file is handled in script.js. Lastly, an important thing to note about using
type="module" is that it will also set the defer attribute on your script tag as well. If you are
unfamiliar with the defer attribute you should read my defer article that covers everything you
need to know about the defer attribute.
Privacy - Terms
https://blog.webdevsimplified.com/2021-11/es6-modules/ 6/8
06/09/2022, 10:36 ES6 JavaScript Modules
* Imports
Sometimes when you import a file you want to import all the exports from that file into one
object. This can be done with the * syntax.
The AllImports variable in this example will include keys for all the named exports and also
will include a key called default which includes the default export. In our example this means
we will have an object that has a key default which represents the User class, a key called
printName for the printName function, and a key called printAge for the printAge
function.
An alternative syntax for the default export would be to include it in the named exports section.
As we found out in the previous section the default export has the name default . This means
you could write { default as User } to import the default export if you wanted.
While technically you can do this I find the syntax is clunky and harder to read than the
standard import syntax I explained earlier.
I talked earlier about how you must include type="module" in your HTML to ensure the
browser knows how to handle the new module syntax. This works fine in browsers that support
ES6 modules, but in older browsers that do not support modules they will completely ignore
this script tag as if it didn't exist. In order to get around this you can include a different version
of your JS that has no modules at all and add the attribute nomodule to the script tag. New
Privacy - Terms
https://blog.webdevsimplified.com/2021-11/es6-modules/ 7/8
06/09/2022, 10:36 ES6 JavaScript Modules
browsers will ignore this nomodule script tag, but older browsers that do not support modules
will treat this script tag as just a normal JavaScript file.
Now luckily, ES6 modules are supported in 95% of browsers so you most likely won't run into
this issue so I wouldn't really worry about this unless you specifically need to support outdated
browsers.
Dynamic Imports
The final fancy thing you can do with imports is dynamic imports where you only import the
JavaScript code when/if it is needed instead of importing everything at the top of your file. This
is a pretty complex topic which is why I have an entire dynamic module import article already
written that you can check out.
Conclusion
ES6 modules are one of my favorite modern JavaScript features since they make your code so
much cleaner and easier to work with. They also open up many possibilities for private variables
that were difficult if not impossible before modules.
Privacy - Terms
https://blog.webdevsimplified.com/2021-11/es6-modules/ 8/8