|

ES6 Modules With Traceur.js

ES6 Modules With Traceurjs and Systemjs

Let’s now jump into learning about ES6 modules. For this lesson, we are going to be making use of a fantastic piece of software for modern JavaScript development. Traceur.js by Google is a JavaScript compiler that is super easy to use, and is great if you don’t want to be bogged down by a massive build system. All you have to do is include Traceur in your page, and you’re good to go. It also allows for ES module loading. The goal of this tutorial is to be able to fully explore the features of ES6 modules, without having to worry about getting excessive tooling configured and set up. Let’s dig in to ES6 modules now!


ES6 Module Playground

To get started, we need a simple HTML file set up for us which includes the Traceur.js JavaScript files we need so we can quickly start testing out our modules. This is the base HTML file we will use for the duration of these exercises.

The source for these JavaScript files to include in your HTML can be found at the Traceur.js github page. You can download them manually, or use NPM or YARN to install the package for you. For this tutorial, we used the command of yarn add traceur, then grabbed the files we needed from there. The base.js file is simply our own JavaScript file that is the main entry point of modules into our pages. We no longer have to declare multiple script tags to include various JavaScript files when using module loading.


Traceur Overview

So what are these extra files that we are including in our test page? These files come from the Traceur package. Traceur is a compiler / transpiler which allows you to make use of all the future JavaScript features that are not currently a native offering in modern web browsers. In addition to making all features of ES6 available to you, Traceur also supports some ES.next experimental features. If you are familiar with how BabelJS works, Traceur shares many of the same features. You can also try out Traceur online to see how it compiles down your ES6 code.

google traceur transcoding demo


Using System.import

For our first example, we will simply demonstrate how the System.import(); syntax works. We use System.import(‘./base.js’); to import the base.js module. Let’s see it in action.

base.js

index.html

system_import_es6_example

What this shows is that as soon as you load a module, or file, using an ES6 module loader – any code contained in that module is immediately executed. A module is executed only one time, the first time it is loaded. Let’s try a few more things.


Testing variable assignment in Modules

base.js

index.html

variable assignment es6 module


Using import and export in ES6

The import and export commands facilitate a basic means of communication between modules. This is how to share information between one module to another. This basic example here shows us exporting a value from the emulatormodule.js module, and then importing that value in the base.js module.


Simple variable export / import

This is the most basic example of an export from one module into another. All we are doing here is using the export command in emulatormodule.js to export the emulator variable. In base.js, we make use of an import command to accept the export. When we log out the value in base.js, we do get the value we expect.

base.js

emulatormodule.js

index.html

es6 import and export


Multiple variable export / import

You are not limited to how many values you can export and make use of in a module. Here we extend the first example and export a game variable as well as the emulator variable.

base.js

emulatormodule.js

index.html

exporting multiple values from one es6 module


Using as keyword for an alias on import

In this example, we have changed things up a bit in the base.js file. Note that we import emulator, then use the as keyword to assign that value to Gamecube. We can then use Gamecube as the variable in our code rather than emulator. Do note that once you alias a variable, you must make use of the alias name and not the original name. Once the alias is set, the original name is now undefined.

base.js

emulatormodule.js

index.html

exporting multiple values from one es6 module


Using a default export

Here we import something that does not seem to make sense. randomvalue does not exist in emulatormodule.js, so how can we import it? Further, there are no curly braces surrounding the value we want to import. When you omit the curly braces using an import statement, ES6 will look for the default export of the module you are importing from. In our emulatormodule.js module, we have set game as the default export. When we run the code, you can see this is the value that gets imported in base.js as randomvalue and Sonic Unleashed is output to the console. Note: Modules can have only one default export.

base.js

emulatormodule.js

index.html

es6 export default


Importing using the Wildcard Operator

If you have multiple values that you want to export from a module, you can make use of the wildcard operator in the receiving module to import all of them at once. It’s a really nice way to shorten up your code. When we export the three values in this example here, they are all imported into values as an object. We then can access those values using object notation.

base.js

emulatormodule.js

index.html

es6 wildcard import


Named Exports are Read Only

As we have been exporting values from our module and importing them in the base module, we are getting a good idea of how they work. One thing to be aware of however is the named export is a read only value once it is in the base module. For example, when we export the game as ‘Sonic Unleashed’, that named export can not be mutated once in base.js. Let’s see this in action.

base.js


Properties of an Object that are Named Exports can be updated

The way that we deal with this is to export values in an object if you want the ability to update them at a later time. In this example we make use of an object to export. As we can see values.game updates nicely this time around.

base.js

emulatormodule.js

index.html

object properties on named exports can be updated


Exporting a Function

We can also export a function from one module to another. Here we set up a playGame() function in the emulatormodule.js module and export it to the base.js module.

base.js

emulatormodule.js

index.html

es6 export function


Exporting multiple Functions

If you need to export more than one function, go right ahead. We’ll export two functions here and see the result.

base.js

emulatormodule.js


Exporting a Class in ES6

You can also export a class using ES6 modules. Here we have our standard base.js module, but we have created a new module of Games.js to hold our games class. Yes, we can now use the class keyword in ES6 to more closely resemble the style of programming you may do in C#, Java, or PHP. Exporting the class is as easy as any other type of export we have done so far in this tutorial. All you do is place the export command just prior to the class keyword, and your class is exported from that module. The related import command in base.js behaves just like you expect it would.

base.js

Games.js


Importing a Module with <script type=”module”>

When you have a web page that includes Traceur, you can also import a module directly in the page by using a script tag and setting it’s type to module. In this example we add bootstrap because I’m a sucker for making things look good with no effort. We’ll take our example of a Games class and use it right in the page using that new <script type=”module”> syntax. Pretty much everything works as in our last example of a Games class, but this time we nave a new method in our class listgames(). This method reaches into the dom and creates a list of our games using bootstrap styling to make it look nice. Recall in our last example all we did was log out the values to the console. This rounds out our examples for nice effect. Check out this concept in action here.

es6 script type module


ES6 Modules With Traceur.js Summary

This concludes our exploration of ES6 modules while using Traceur.js. It turns out, there are many other ways to handle working with modules such as Babel, Webpack, Rollup, Browserify, etc, etc. In some ways it almost feels like the days when we had jQuery, Moo Tools, Scriptaculous, and others vying for the position of the defacto dom manipulation library. We are now seeing how ES6 tooling will evolve. Over time, it is likely these tools will consolidate and a clear leader will emerge with a somewhat standardized way of doing things. Until then, we are all experimenting as the JavaScript ecosystem moves into the future.

During this tutorial we covered setting up a basic ES6 sandbox for testing our module loading and went over a high level overview of Traceur and how you can use it. We then took a look at how to load modules as files, leveraging the power of the System.import(); syntax in our main HTML file. From there we tested a variety of exports and imports between ES6 modules including variables, functions, and classes. Finally we wrapped it out with an example of making use of the <script type=”module”> syntax to embed an ES6 module right on our page.