7.6 ES Modules
ECMAScript Modules (ES Modules or ESM for short) are one of the greatest features of JavaScript to emerge in recent years. In this lesson, I'll show you how to make use of them for more modular, maintainable JavaScript.
Key terms:
Hi, folks, in this lesson, we're going to look at using ES Modules. So right back at the start of the course when we did the set up, I mentioned that we were gonna be using SystemJS. And that we didn't really need to use it for much of the course, although it's useful. But there was a particular reason that we did need to use it, and that reason is because I wanted to show you ES modules. Now it's slightly unusual in that the module specification itself is a part of the official JavaScript specification. But module loaders are not yet part of the official specification. So we're in this situation where the syntax for modules themselves are supported, but, loading those modules is not yet supported. Now browsers have started to introduce support for loading modules, but at the moment these are behind settings flags in the configuration sections of browsers. And some browsers haven't even implemented the loaders at all yet. So SystemJS has its own module loader, and it fully supports ES modules. So with SystemJS we can get all of the benefits of using modules and have those modules supported by all common, modern, mainstream browsers, so we get the best of both worlds. So first of all then, let's create a new module. So as you can see, there is nothing special about module files, they aren't some crazy new type of file, they're just JavaScript files. What determines whether a script file is a module or just a regular script file is how that script file is loaded, not how it is defined. So in order to export a value from a module, we need to use the export keyword. So we can export many different things from within a module. We can export values, like we have done here, we've exported a constant value called STR, and that is a simple string, but we can also export classes if we want. And it's this class exporting that makes modules really, really powerful. We're not gonna go that deeply into modules today, I just wanted to mention that, that is one of the great things about modern JavaScript is we can have our projects, which is super organized, into lots of small modules that we can then put together in interesting ways. It makes our projects, much, much more organized, and when you start doing it, it just makes JavaScript development awesome again. So, we've exported this value from module a, so now, we want to import module a and we can do that into our index file. So in order to import a module into another file, we use the import keyword. Now we need to import something specifically, and in module a, we exported the constant str, so that's what we're going to import. So we're importing something called str, that will be made available throughout the rest of this file now as if we had to find str as a variable directly in this file. But we still need to tell the index file where we want to import this from, we do that using that using the from keyword. We just need to specify the path now to the file that contains the module. One thing that you might notice is that we have wrapped the identifier that we are importing in curly brackets, this is very similar to de-structuring assignments. We're creating this str variable within curly brackets, and it is now as if this str was just a variable that we defined within this file instead of within a completely different file, and for now, let's just lock this out of the console. And in the browser's console there, we can see the message that we exported from module a. We haven't had to do anything special to the browser, SystemJS is taking care of it for us, all we've had to do is define our module and then import the module somewhere else, into another file. So, another type of export is called a default export. So let's go back and change the export in module a. So this time we're making the same string as before a default export, and let's see what implications this has. So back in the file that we are importing, this str value doesn't actually point to anything anymore because module a doesn't export str anymore. So back in the browser our log message is just undefined, but that doesn't matter, because all we need to do is get rid of the curly brackets. And then whatever we specify becomes the export from the other module. And now everything is working again as before. So previously when we had the curly brackets, we didn't get to decide what value the imported value could be accessed through, the module defined that. But now that we're using a default export in the other module, we do get to decide what we call the imported data. So in this case we left it the same as it was previously, str, but we could call it anything we want, it really doesn't matter. And it continues to work exactly as it should. So that's really one of the benefits of default exports is that the consumer gets to decide what that imported token is referred to as. We can also export multiple values from the same module, there aren't any restrictions. We aren't restricted to just exporting a single value, we can export 100 values if we want. But we can only have one default export from a module. You probably have noticed that I commented out the IIFE and the use strict directive in the index file. Now there's a very good reason for that. So the reason why we've commented out use strict is that anytime we use modules, the code from within the module is always run in strict mode. Now strictly speaking, if you'll excuse the pun, we shouldn't have commented out use strict in our index file. Because our index file isn't actually a module, it's module a, which is the module. But we didn't have to add use strict within module a, because all modules are always running strict mode all the time, there are never any exceptions. So when we're working with modular JavaScript applications, we don't need to worry about specifying that we want to use strict mode, it will just use strict mode all the time. The reason why we have commented out the IIFE, and because index isn't actually a module, we probably shouldn't have commented out in this case, but I really wanted to make an impact here. Unlike with regular JavaScript files, values and variables that we declare inside a module will never become part of the global scope. So even though the code within module a is not wrapped in an IIFE, we've used the var keyword here as well. We aren't using let or const or any special kind of scoping, we've just used the regular var keyword, and we've declared a variable. So if this were a regular JavaScript file, that variable would now be global and we'd be able to access it from anywhere else at all. Let's go back to the index file and just try to access that. And we can see that it's undefined, even though we've defined the variable as if it were a global and a non-module, because it's a module, it doesn't become a global variable, that is insane. It means that we can just lose all of this IIFE boilerplate that we've added to all of our JavaScript files for years and years now. We can just forget about it completely, as long as we're using modules, we can't accidentally set global variables, that is incredible. So, in this lesson we took a quick look as ES Modules. We saw that when working with modules all we really need to learn is how to export values from modules, and how to import them into other modules. We saw that we export values using the export and optionally the default keywords. And we saw that we can import values from modules using the import keyword. We saw that when importing regular exported values, we need to use curly brackets and match the names of the identifiers being exported. But when we're using default exports we can just import them and give them any label that we want. We get to choose the identifier when we're importing a default export. So this now brings us to the end of section seven of the course. In the next section we're going to move on to look at working with the DOM, thanks for watching.