This course has been updated! We now recommend you take the ES6: The Right Parts course.
Transcript from the "Modules" Lesson
[00:00:00]
>> [MUSIC]
[00:00:03]
>> Aaron Frost: Modules, it's hard to discuss. Because there's not any great support for it right now. It's changing even a lot, recently. So no one's really had a lot of time to get in there and implement it. So a lot of the decisions are made, and people keep saying, no.
[00:00:19] And by people, I mean the people who understand it. They're talking about how great it's going to be. It's hard to really show off, though. Like in code. Because I can't really have you guys, like, there's no way to mess around with it. So it's really only available via polyfills right now.
[00:00:35] It's still super fresh. Let me show you guys this. So these are their notes from June, right? They just barely met in June and made some fairly major discussions to it. These are their module breakout session notes. They made some changes, significant ones even, in June. So, when I say it's still fresh, I mean, it's still one of the ones they're still talking about and trying to make sure they get right.
[00:01:06] And it does have the least amount tooling of all the other things that we've talked about, so. Who here is familiar with modules like CommonJS and AMD? We kind of get them? Yeah? Okay. So a lot of us kind of get them. They've got bits from both. Both have their merits.
[00:01:22] When Dave Herman and company set down to spec out what modules would look like, they came up with some goals. And they wanted to make it similar to both. So it's similar to CommonJS in that it favors a single export. In CommonJS, you can export more than one.
[00:01:42] But it really kind of lends itself well to that single export. And it also supports cyclic dependencies. So, if A depends on B, and if you try and import A, and B depends on A, that's okay. Cuz otherwise you'd have an endless cycle. And that's something that other module systems will support.
[00:02:04] But it's similar to AMD. And it has async loading support and configurable module loading, okay? So let's kinda talk about this stuff. The major design goals, when they sat down and talked about them, they had a lot, but these are some of the default ones. So default exports are favored.
[00:02:24] They wanted a static module structure instead of a dynamic one like we can get in other systems. And they also wanted these the support for the sync or async and then the cyclical dependencies. So let's start with each one. Import/export syntax. So there's two pieces inside of.
>> Aaron Frost: That you really need to focus on.
[00:02:49] The one is the import/export syntax. Because as you're writing your code, you need to export it, and then you also need to import other people's code. But then there's also this programmatic loading API that they've built as well. So let's talk about these two things. Let's talk about the import/export syntax first.
[00:03:08] So if you want to do like this single export, you write your class, and then in your MyClass.js, you say, export default MyClass;. So the word default is a keyword. And that means when they import it, whatever the default is is what they're gonna get. Like, that's gonna be whatever, the thing that gets imported.
[00:03:32] So if someone imports, if they were to do this, import MyClass from 'MyClass';, that's what they're gonna get. They're gonna get a reference to this MyClass constructor, okay. So that's kind of the basic import/export syntax. If you had some library, and it was like, hey, export this constant square root, export the square function, and export this diag function.
[00:04:04] And then in main, if you could import only some of, you could, if you wanted import only some of them, you could. So if you were like, hey, go ahead and import just square and diag from lib. And it would see lib and it would know to go ahead and asynchronously, it would load that and go ahead and import those.
[00:04:24] And then you could, you know, square whatever you wanted to or you could call diag or anything. Does that make sense, how you're gonna import functionality from other stuff? You could also, if you wanted to, you could call import * as lib from 'lib';. And then instead of being able to call square, you have to call lib.square or lib.diag.
[00:04:50] So that's other syntax on top of it. So if you wanted to alias what you're exporting, you could say, export MyClass as Dude. And then you could import Dude as Bro from 'lib'. So you can alias them on the export, you can alias them on the import as well.
[00:05:09] Make sense? And bro is an instance of MyClass, like if you were to do that, it would work. Okay. So, cyclic dependencies, so import Main from 'main' and import lib from 'lib'. That would be like if, no matter which one of these things you required or that you imported from a third module, they would both sit there and have this cyclical dependency on each other, but that would be okay.
[00:05:37] Like, it would load the dependencies of the imports first and then it would run them, so.
>> Off Camera 1: And main and lib strings, are they normal paths, or?
>> Aaron Frost: Come again?
>> Off Camera 1: Are they paths, or what, file paths?
>> Aaron Frost: Yeah, they're paths.
>> Off Camera 1: Okay.
>> Aaron Frost: Yeah, yeah, yeah.
>> Off Camera 1: So they don't have to be in the same directory or anything?
[00:05:54]
>> Aaron Frost: No.
>> Off Camera 1: Okay.
>> Aaron Frost: Yeah. So here's a different example that uses file paths a little bit just to kind of show it off a little better. So like in lib, if you wanted to import, you could import the default thing or you could import some named things from mylib.
[00:06:13] That's one syntax. You could import just the default, or you could import just the named things, the properties on top of it. You could rename them if you wanted to. So if you were like, hey, import named1 as myNamed1, and then import named2 as well. So that's one way.
[00:06:35] Importing the module as an object with one property per named import. So import * as mylib, and then anything exported you'd call as mylib.foo and mylib.bar. And then if you only wanted to import the module but not actually do anything with it, you could just say import and give it the path, because that might be a thing you wanna do.
[00:07:00] Like a polyfill, you know what I'm saying, or, I don't know, something. So that's an option. So here's how you export, you'd say export var myVar, export let, export const. You can export a function. You can export a generator. You can export a class. If you put the word default in there anywhere, that will be treated just like the default thing.
[00:07:29] Otherwise, this export class you'd have to specify, like, it would only be like a like a dot dependency, it wouldn't be the main export, if that makes any sense. Exporting, you can say export *. So I could re-export, if that makes any sense. So let's say I want to import something, like import foo from foo.js, and then I want to export it back out to someone else.
[00:08:00] You could just use this syntax, export * from some other module. So that would basically bring it and go ahead and export all of its stuff back out. Awesome, weird? It's awesome. You can export foo or bar from that other module. Like, you could export just pieces of it if you didn't want to export the whole entire thing.
[00:08:24] You can use the as syntax as you're reexporting as well, okay.
>> Off Camera 1: Can you maybe give a use case for that?
>> Aaron Frost: For what, the aliasing or the reexporting?
>> Off Camera 1: The reexporting.
>> Aaron Frost: So let's say that you had some module that was like, I don't know, some extension of the web socket object like I showed earlier.
[00:08:56] And you were like, hey, if I'm in IE, import this thing, and export it out. I don't know. Yeah, that make sense?
>> Off Camera 1: Yeah. [LAUGH]
>> Off Camera 2: Maybe you want to create a library and you want to split it into a bunch of different files [INAUDIBLE] and then just reexport them from one place, so you can just import that whole library into files, things like that.
[00:09:21]
>> Aaron Frost: Yeah, kinda. I don't know, I've never done this. I don't even know if it's possible in CommonJS. But, I mean, I imagine in CommonJS, you would just be like, require, or var foo equals require foo. And then I can say, export.foo equals foo. So I could reexport, I've never done it, though, so I don't know.
[00:09:42] Yeah?
>> Off Camera 3: Are the paths relative to the current file?
>> Aaron Frost: That's a good question, I don't know. I couldn't try it out. But that's a good question. So, I wish I could have tried that out. I knew you guys were gonna ask, though.