Transcripts
1. Intro: Hello and welcome to
my course ES6 modules, how to use them and
how to create them. Es6 modules are the
new standard for loading modules in JavaScript, which is supported in
all modern browsers. It has a new syntax and extra keywords for
importing and exporting. Almost all modern
browsers can use it. They have integrated
module loaders and also no jazz in its latest
version supports it. Then every modern transpiler and Bundler and also
TypeScript supports it. New projects starting out use the new module
system and more and more of the existing projects
are updated to support it. And it also helps with tree shaking and minimizing
the bundle sizes. So if you're using ES6 modules, you're on the right
track for developing modern and
maintainable web apps. So in this course,
you will learn how to use the Export and the import statements
and how to integrate modules into your HTML page, how to use dynamic imports
and how to use the syntax. I hope you will enjoy the course and see you in the first video.
2. Import and export: Hello and welcome to this video. I will explain in this video
how to use ES6 modules, how to input them, how to create them, and how to integrate
them into your HTML. First, let's talk about shortly about my development
environment. I have videos to
recode as an IDE. You can use that too. It's a great idea
from Microsoft. It's free. You can download
it for my girls, for Windows, for Linux. But you can also
use something else. You can use your favorite
text editor, whatever. It doesn't really matter. And I'm using a VGS
as a deaf server, which is transpiring
code on the fly. But you don't have to use it. You can use anything else. You can use a normal server, you can use a webpack, dev server, anything you like. So let's get started. And every web page and every rep application
starts within HTML, in this case, index.html. And here it is. It's quite simple. It has the title
VII tab because I'm using create VT to
create a project. So I have this div here, which only contains
little texts. So that doesn't matter. But here we have the
important first tag. It's the script tag of course, because it's, it's
loading a script. In this case, it's
the sauces main JS, which is over here. We check it right now. Main JS, at the
moment it's empty, but I will put in
some code there. So you could also put some code here inside the script tag and
then omit the source. That's also possible that
you should already know that it's normal script tag. It works like a
normal script tag. Only difference is you
have type module here. And this the important
thing if you want to use keywords are statements
like import and export. In the script, you have
to use type module here. There's another possibility too. Do dynamic imports. You can use the import function and you can import modules, ES6 modules with that. But the standard way to statically referenced them is the script tag and type module. So this the important
thing, type module. And you can write your
code here inside, or you can use the source attribute and point
to your JavaScript. So let's check if this
is really loaded. So I put a year some log, Just main JS, and let's
check the console output. Okay, so here we have it. That really works. So our script, our
module, is loaded. And at the moment, it's not visible
that it's a module. But we will put in some
modules specific code here. So at the moment
we have this log, we can leave it here. But what is the important
thing in the module? It is that the module can export something or you can
import something or both. Of course, I'm doing
here the import first, of course, because exporting
here doesn't make any sense. Because I'm loading this
via the script tag here. And I cannot use
any export here. So we have to use
first some import. So I'm putting an
import statement here. This is the new thing. This is the ES6 module
import statement. And so now we have to
write import something. And then after that from
and you can read that as import something which we
specify later from the file, which is specified here, which is I created mod one. So it's mod one dot js. Please use the extension here. I could also omit
the extension here, but this is because I'm using
VHS as deaf server and it can resolve also the modules
without any extensions. But I think it's best practice to put
in the extension here. So it could also be
something like JSX or you can also if your, if your environment supports it, you can also use, you
can also import CSS. But for that you need
some kind of a bundler, or in this case, the jazz deaths have also
supports CSS importing. But normally you import
a js dot js file. So we are importing
from this file. And here we need to tell the JavaScript
engine what to import. We can import different things. We can import specific
exports, single exports. Or we can import a
default, a default export, or we can import the
complete module, which I'm doing here
with this asterisk. And then I need to put
them some identifier. I can completely make this up. So I'm using mod one. It doesn't really matter
what the identifier is. I can reference the module
with this identifier. So I can write here
mod one dot something. It's empty at the moment, so I don't have anything here. So I'm just writing mod one. But the important thing
here is the asterisk. As mod one means I'm importing the complete
module as an object, and I'm naming it mod one. So this is my identifier for the module, the
complete module. Let's go to the mod one module. At the moment is
completely empty, so there's nothing to
be imported actually, but we put in something here. We're importing something. So I must export
something in this module. And this is where we
use the export keyword. And after the export, we need to specify what
we want to export. And I'm exporting
a function here. And I cannot, I cannot export
and anonymous function, I must name it here. So we name it, do it because it's
just doing something, something like this console log. I'm just logging. Do it. Okay, so here we are exporting
this function in main JS. I can import that and I'm
inputting the complete module. So I should be able to do
something like mod one dot, do it, and call it here. Let's check if it's working. Hello modules, that's
our div, doesn't matter. Important thing is
here in the console. Let's do it. This is what we,
what we log in the, in the export at function to it. And then we have main js. Let's check back the code. Yeah, So we are calling the
export function, do it. And in this function we're
doing console log it. And after that, we do
console log main JS. So that did work
already. So that's fine. Let's export second function. So we copy this one and
name it, do it too. We locked to its to the console. Okay, so what we should do here, what we should be able
to do here is do it. Do it too from the
mod one module. And is already
suggesting me do too. And let's see if it works. Do it, do it too. It works. Okay, So we export it
to functions here. Export function, do it. Export function due to the
syntax is straightforward. You just put the
export statement before the function here. And you can also
export variables like liger, const, for example. This is a constant. I'm exporting this here. Mod one dot. This is a constant. And I can just
console log it here. And let's check if it's working. Yeah, so it's outputting
to here. So that works. We can export functions, we can export variables. So let's see if we can import a specific function
or specific export. So here we have the syntax too. Import the complete module and reference it as this
identifier mod one. I could rename mod
one to just mod, for example, I can call
it anything alike. But now if I want to
import a specific export, I need to use different syntax. The syntax here is
the curly braces, which is also used
for structuring and which is kind of similar. So I'm putting here
these curly braces and I'm getting this the exports here as suggestions for import. So I have to do is to, and this is a constant as the exports from this
mod one dot js module. Let's import, do it. And we're commenting
this out for the moment. And now I have imported do it. So I need to remove that because I just have do
it now as an identifier. And I can call do it as
a function because it's, it's exported here in mod one. And I'm importing just this one, export, this one function here. And it's called the same as
it is exported here, do it. And I'm calling it. So let's see. Now it's working. I could do the same with due to an actress all kowtow could
also import the const. So right now I'm completely importing every
export here separately. I could call do it to
an icon console log. This is a constant. And we should have the
same output as before. It's due 22. So far so good. So we can import the
complete module. You can import single
exports or you can, you can import them separately
here, like I did here. What if you want to call it? Let's say you have already have a function
which is called to do it. You don't want to
change the name because you want to use it here. And this one is just
doing console log. And we'll output Local. Do it. So now we have a problem because we are defining here this
function do it, and it's the same
identifier as this import. But how can we import this and rename it to
different identifier? This is possible with the same syntax as we did
before with the star. As do it, as, let's
say, imported. Do it. With this syntax. We renamed the export to this
identifier imported, do it. Let's see if we can change
this one to import it, do it, and see what
the output is. So let's do it. Do it
to two and local dude. That's what we expected now. Because here, this do it is, of course this
function declaration. This do it and the exported
do it from this module. We, we renamed it
to import it to it. And you could do the
same year if you like, do it to imported. So if you already
have and identify in your module scope which is identical to an
export of a module. You can use this syntax
to rename the import. Let's check if it's
still working. Yeah, it's working. So this is how you import
exports separately. And this is important because
you could also of course, import all with always with a star and important
complete module. But it's a problem because
you don't tell the bundler or the program that you use to bundle your JavaScript and
minified and stuff like that. You don't tell this system what you actually use
from this module. If you do this and
just want to have, let's say you just
wanted to have do it. So i'm, I'm commenting this out. If you just want to have, do it as important to it. The bundler, if it uses, for example, it's something
like three tree shaking. The bundler knows
that you only use, do it this function
from this module. So theoretically if
nobody else uses, are no other module
users do it too, or this constant, the bundler
could just erase this code. And so make your
bundle size smaller. This is the advantage
of this syntax here you just import one single export. So you should
prefer this syntax. You can also, of course, if
you use the complete modular, almost any, almost
all the functions or the exports in the module. You can, of course,
use this syntax. So, but if you, let's say you have
something like low dash, which contains like 3030
exports or something like that. And you just need one function. It would be wise to just
import this one function. Because your Bundler would then erase all the
other functions. You have a much
smaller bundle size. So I'm going back to this. Now. Let's, let's jump right to different syntax or a
different import style. Let's call it like that. What we can also do is we
can define a default export, default, export, default
after the export. And I'm telling
the module system that this is my default export. Of course. What can I do here to import the
default export? So let's say this is
my main function here. This is where, let's say 80% of the module users want to use. Or it's, maybe it's
also the only function. Let's, let's do it like this. It's the only function
is the only export. So you can, you can say export
default function do it. And what you can do here is you can just
write it like this. We'll change it to do it. And I'll erase this one. Let's check in the
browser if it's working. Do it. It works. So if you ride export default, you can import this default. In this way. Just write import,
then any identify, I could use a
different identifier here I could use imported. Do it. Doesn't matter because
this syntax is for importing the
default export. So I can name it as I like. Still working. Doesn't have to be
the export a name. So I could call it anything alike because I'm
not specifying. I don't have to specify what
I want to import because this syntax is for
importing the default. Of course you have to have a
default in the other module. So if I erase that, it shouldn't work anymore, I get a syntax error. Requested model does not provide
an export named default. Okay? So doesn't work. Of course, I have to mark the export as default
to import it as a default. So here you can put in
some, any identify you, you'd like to import the
default export here. And I can have a second
export, which is not default. Of course you can only
have one single default. But I can have a second one. That's not a problem. So how do this import
I, of course I can. Right to import statements. The first one is
importing the default, and the second one is importing. Do it too. That's completely possible. So I call it here, do too. And it should also work. I think I didn't change
the console log here. So now do it and do it too. Okay, so that's how you use the import with
a default export. You can also, you can
also combine this. So the syntax is also possible. So if you want to import
explicitly in this curly braces, in these curly braces, you can also explicitly say, I want to import default, name it important to do it. You must provide an
identifier, of course, because this doesn't work, because you need an
identifier here. So you can do this. So as soon as you put a
default before the function, you will need to consider
this here and import it as default as and
then some identifier. Or you can, of course, use the much shorter expression and import it like that. Of course it's double now. So I should comment this out, or I just delete that one. Default as important to it. So that's totally fine. Let's check it.
Okay, it's working. Okay. So this is how you import, and this is how you export. And in the next video we will
talk about dynamic import, which is Yeah, it's just a function you can use
to import modules. And you can use it to delay the loading of
a module, for example. That will be the next video
and hope to see you there. Bye.
3. Dynamic import: Hello, Welcome to this video. Here we'll explain how
to use dynamic imports. So let's say we want
to load a module, but not at the beginning of
the load time over the page. But we want to load it later. Maybe wherever UI component, which is quite big,
as many dependencies. So we don't want to
load it at the start. At the beginning
of the page load. We want to delay the
loading of the module. To a later point in time. The user navigates, for example, to a new page. At this moment,
the module will be loaded and not at the start. We can simulate this. Because we don't have
user interaction here in our webpage at the moment, we can simulate this by using a setTimeout with the
delay of a 1 second. And here we can try
to load the module. Let's be naive and try this. Just erase this here. We don't need that anymore. Just put the import statement
here in this function. So that doesn't work. It's already marked as an error. We tried anyway. And see what the browser says. Uncaught syntax error,
inspect unexpected token. Okay? So this is the, the error message
which is not quite, not quite explanatory,
but I will explain it. This is the static
import statement. And steady means it has to
be at the top of the module. So it must be here. And you also, normally, you're not allowed to
do this for example. So it is working here. But I think in the
specification, it says that nothing else should come before the first
input statement. Nothing in-between. So you should put
your, all your inputs, your static imports at
the top of the file, at the top of the module. So we've tried that. That doesn't work. But
there's another possibility. And it's the import function, the dynamic import function, which is also called Import. And it's a function
so we can call it. And we can give parameters. And the parameters,
of course, the from. So where to get
that module from. So we take the same path, the same module as with a static import and check
it out what the result is. So there's nothing
printed out here. Which is not very surprising because we're
not doing anything here. So if this module's only loaded, there is no code to
be executed here. Only the function declarations
for do it and do it too. So that seems to work. We can also write a
console log here to see that it is really loaded
and really execute it here. After 1 second, mod one. Let's reload the page. After 1 second we see mod
one printed out here. Okay, so that seems to work. But okay, so how do we get our module or the
exports of the module? We could try something like that and put a debugger statement here to check it
in the debugger. Okay, so it's
stopping here and we check what is returned
from the import function. Okay, this is not the
module, as we can see. It's a promise, a
so-called promise. If you don t know
what promises are, I'll explain right now. But it's not what we
may have expected here. One could think that, okay, so important is returning the module, the
important module. But it is not. Instead
it returns a promise. And the promise is something
for asynchronous tasks. So import is loading a
file from the server, which is naturally asynchronous. So it needs to get
to the server. And the server needs to
send the module code. And then the JavaScript engine
needs to execute the code. So this is something which would block the JavaScript engine. So this is why it
is asynchronous. And for asynchronous processes, we have the promise API. If you're not familiar
with the promise API, we can check what is, what are the properties
of the promise returned. It already suggests
catch finally, and then the important
thing is done here. Then is a method on the promise. And it takes a function. And it also, this
function has a parameter. In this case, it's the module. So I should call this promise. And so we have a promise and
we have the method then. And then method gets a, you can call it a callback
methods, callback function. And this callback function is called if the
promise is resolved. And in this case the
promise is resolved when the module was loaded. And the parameter of the
function will be the module. We can check this
if put a debugger here and delete this one, we can check what mod is. And if my assumption is true, just reload the page
nafta 1 second. We are really coming to this debugger and
we check module. And yes, this looks
like a module. It's also called module here. And we have the default export here in the default property. And we have do it to. The default function
was called to do it, but it's, you can find
it here on the default. So the actual name is not used as a property name
by default is used here. And the second export
was to do it too, which is accessible
by the same name. So with this, we
have the module. Here, we can use
it. Let's do it. And suggestions already there, default or do it too. So we use first the default. And then we can use two to two and check what
is printed out. So we have mod one, which is printed out at
the start of the module, of the loaded module. Then we have do
it and do it too. So that's what we have
expected and it's working. This is not very nice syntax that you can write
it in a better way. And for that we can
use the async await mechanism or the
async await syntax. If you have a promise, a return value with a promise like you
have with the import. You can call or you
can write a weight. And that means we are waiting. We are awaiting the
resolving of the promise. So it's the same as here in
this call back function. Except that it's not
a callback function, but it's kind of normal
code as you write it. In normal situations,
synchronous situations, the only differences we
have this await keyword. So I could write something like constant mod equals or is
assigned a weight import. So this await, waits for the
resolving of the promise. And the return value. Or the, in this case, the module will be the
value of this expression. And I'm assigning it to mod. And then I can call
do it and default. And due to, that should work except for
I forgot something. And that is the async
keyword over here. So if you're using a weight, you have to use async in the function you are
using the weight in. These two go together. If you have a weight, then always use async. In front of the function. Except for you can also use
it on the top level here. And then you don't use the async because you
don't have a function. But as soon as you have
a function that we have one because we're
using setTimeout. You have to use
the async before. Before the function. You can also use a normal
function like this. And before the function keyword, you have to use async or before the 40 error function is
shorter syntax for this. And if you use the async, you can also use the await. Await can be used
everywhere where you have a return value of a
promise or you have a promise. So you can await the
resolving of the promise. There's also function in
the browser called fetch, and it is also returning
a promise and you can also use await with that. For example, it will be
something like that. Await and here you
would put the URL. Well actually we can use it. We can check out mod one dot js. We can load it as text. So let's check what
response will be. This has nothing to
do with modules, but anyway, it has something to do with
promises and the weight. So I'm showing it
here the response. The response is a
response object. To get the actual texts, we need to call something
on the response object. And this text. And this is also returning
a promise, as you can see. So we already know
how to use promises. So I'm signing more texts with a weight, responds to text. Dot text is also
returning a promise and I'm waiting for the
resolving of this promise. And then I'll get the mod text. Let's check it. More text. Yeah, and then we have our
text of mod one dot js. So this little
excursion for promises, which we have to use here. So either you use dots then
with the callback function. And this callback
function is called whenever the promise
is resolved. Which in this case is when
the module was loaded. Or you use the much nicer
syntax await import. And then you directly
get the molecule. And then you can use the
module as if you would. Write a static import mod from dot mod one, JS that will be the same. So in this case mod
would be the same. You can call default
or do it too. So we can test it here. Yeah, So I'm reloading. First. It's writing, do it, do it too with the
static import, and then do it and do it
too with a dynamic import. Static import, and
here, dynamic import. So if you want to load
a module just in time, for example, if the
user navigates to a new page and you want
to render a new control. Then you can use
the dynamic import. And it returns a promise. And you have to either wait the promise or use
the dot then methods. And then you get the module. Just like if you would
use this syntax.
4. Conclusion: So in this video, I will
conclude the course and summarize what I've showed
you about ES6 modules. We've seen how to
integrate modules into HTML with a script
tag and type module. So this was our first
module here, main js. Then we've imported
the second module in our first module
into our first module. And this is the second module. We have exported
two functions here. One is a default
export and one is not. And you have seen how to
import the whole module, the complete module
with this asterisk. We have also seen how to
import only specific exports. So for example, here we
import only do it two. Or we could also import
default as do it. And finally, we've seen how to use the input
function here, which is used to dynamically
load modules at runtime. And we have learned
how to use the promise API and how to use the new
keywords, a single weight, to use the import function
and immediately get the module so that we can call the exported
functions here. So I hope you've
enjoyed the course, and I hope that you are now able to use ES6
modules successfully. And with a bit of confidence. Feel free to check
on my other courses on web development
and JavaScript. And good luck to
you and goodbye.