Deep JavaScript Foundations, v3

ES6 Modules & Node.js

Kyle Simpson

Kyle Simpson

You Don't Know JS
Deep JavaScript Foundations, v3

Check out a free preview of the full Deep JavaScript Foundations, v3 course

The "ES6 Modules & Node.js" Lesson is part of the full, Deep JavaScript Foundations, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle discusses incompatibility issues with the ES6 module system and Node.js.


Transcript from the "ES6 Modules & Node.js" Lesson

>> Kyle Simpson: For years, there was clamoring that JavaScript, if the modules were so important as a design pattern, then we ought to have first class and syntactic support for them. And so we finally added ES6 modules. ES6 modules,
>> Kyle Simpson: Are,
>> Kyle Simpson: Well, let me just say they're a work in progress.

It should have been that when the ES6 spec landed, we just had modules and then within a few months or a year, it was just in all environments. Unfortunately, we had somewhat of a process breakdown, to be as generous as I can, in that TC39 didn't really talk to Node.js about their plans for the module syntax.

And Node.js didn't really talk to TC39 about the fact that what they were about to spec was incompatible with Node.js. And so that spec landed, and then a year and a half later, somebody finally realized that the two of them should start talking about that incompatibility. And for the last two and a half years, we've had this cluster f of discussions and, what are we gonna do in this existential crisis of we have this thing that's in the spec and it works in browsers, but the single largest code repository ever invented, aka NPM, it's completely incompatible?

So what are we gonna do? Good news is they have been working on it, some really smart people have been working on it. The bad news is there's only bad compromises when you get that far down the road. And one of those, what I consider to be really terrible compromises, is that to use ES6 modules interchangeably in Node, you're gonna have to use a different file extension, mjs instead of js.

So there's a working group within Node that is working on getting full module support with whatever caveats are necessary, full module support into Node, and they're gonna do it over phases. And they are expected, I think, at this moment, they're expected sometime in Q1 of 2020 to land stable in Node the first phase of three or four phases of module support in Node.

That's like five years after the spec came out. So that's not great that we're having to wait this long. I actually am a big fan of this feature and would like to be writing it, but I have stayed on the sidelines and not adopted this syntax because of the flux.

At one point they were literally saying they may have to get TC39 to change the syntax. And when I heard that I was like, I'm out. I'm waiting for this whole thing to settle down, okay? So some people were early adopters, and they loved the module syntax, and they're writing it all day, and they're having transpilers and whatever.

And that's fine. If you use that syntax, that's great. I'm gonna show you briefly what it is, but I'm just sharing with you from my perspective, I don't use this syntax quite yet until this whole Node thing settles down, yes?
>> Speaker 2: Is there a one or two sentence TLDR about what the incompatibility is between the spec as written?

Does it have to do with or?
>> Kyle Simpson: Yeah, so this is not the complete problem, but this is probably one of the bigger problems. Node wants to preserve the ability for you to do an old style require of a new style ES6 module, or do an ES6 module style import of an old style Common JS module.

And it's not that bad to do one or the other, but it's really crazy when you have a cycle. Where one has required the other, and then imported the other, and things just go completely nuts in those corner cases. And because they have such a large and vibrant ecosystem, they have to worry about all those corner cases.

So there's a bunch of problems, they've been sifting them out, making compromises. I don't like the outcome, but I'm glad that we're at least making progress towards getting something. It's not gonna be amazing, but at least it's something, okay? And when it lands, I fully intend to switch over to the syntax.

But for now, this is one of those things that if I really needed to support it, I would prefer a tool to write me the syntax so that a tool can change and deal with those problems. This is not an authoring format for me. I continue to use the idiom, the classic style.

So here's what the module format looks like. You open up a file and you just start making variables and functions. And that file, because it's gonna be loaded as a module, is assumed that everything is private. You don't need a syntactic wrapper. You can conceptually of think of it is being wrapped in a big function.

Wrapped in a scope that is by default private. The way you make something public is you use the export keyword, like you see on line 3. So anything you export is public, everything that you don't export is private. The other thing to know about modules is that they are file-based.

Which means it is impossible to have more than one ES6 module in the same file. If your application is composed of say, 1,000 modules, the way many of your applications are, and you write all of them in ES6 modules, you'll be writing them all as separate files, which is fine.

But there will not be a way for you to take those ES6 modules in their current form and ever put them into the same file. That's not a thing. So for example, without a build process, if you wanted to ship them to a browser, you're gonna have to load a thousand separate files with all the performance implications thereof.

People that are currently doing this today are using tools where they author in ES6 modules and they compile back to the old school style module and concatenate them into a file and ship it off. And in my opinion, I'm just skipping the middleman. Since we have to compile back to that old syntax anyway, I just keep writing that old syntax.

But some people are finding benefit out of authoring this format. So you make a module and you export what you want. The other thing to know, not only are they file-based, but they're also singletons. No matter how many times you import this module into an application, it only ever runs once.

And every other time that you import it, you just get another reference to that same instance. So if you want to have a factory for your modules where people can make multiple instances, you're gonna have to expose on your API, a factory function to do that.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now