Real-Time Web with Node.js Real-Time Web with Node.js

Extending Modules

Kyle Simpson
You Don't Know JS
Check out a free preview of the full Real-Time Web with Node.js course:
The "Extending Modules" Lesson is part of the full, Real-Time Web with Node.js course featured in this preview video. Here's what you'd learn in this lesson:

Libraries like Browserify allow the modules to be packaged and loaded directly into the browser. Kyle also demonstrates some shell code that allows the same module code to run in the Node, the browser, and other loading scenarios like AMD.

Get Unlimited Access Now

Transcript from the "Extending Modules" Lesson

>> [MUSIC]

>> Kyle Simpson: Now I wanna speak to something else, somewhat related.m You may have heard of projects like, how many of you have heard of Browserify? Okay, over half of you. I will say, I will admit readily that I am not an expert on Browserify. I've used it once or twice, I know about it, I know how it works.

[00:00:24] But let me just explain to you what it does. Let's say we had written some node module, like for instance, our Hello World module, and we wanted for that same code to be able to run in a browser. We wanted somebody to theoretically be able to load up an NPM module, and use it in a browser.

[00:00:43] Well, if it's plain old simple JavaScript with nothing but console statements or whatever in it, no big deal. That code will just run all by itself, but what if it was something that was using some of the built in node libraries, which aren't gonna be present in the browser?

[00:00:59] Is there any way to do that? And that is what the Browserify thing is about. So as an example,
>> Kyle Simpson: If you're using, I know it's a little bit hard to read, let me zoom this in a little bit. If you're using some of the Node APIs that they have listed here, like their events API, the stream, the path, the URL, those are things that can be ported to the browser, and that's what Browserify will do.

[00:01:26] It will actually take your module, and it will modify your module, and it will include whatever is necessary, so that your module will just run properly in the browser. Now it can't do everything, so our module, our Hello World module, is likely not something that could be Browserified because we rely on the file system module.

[00:01:48] And without a lot of work, the file system module isn't just gonna work natively in the browser. And so, I've never tried it, but I don't think that Browserify, they don't have it listed here. I don't think it's able to handle the file system API. But if we had chosen some other API, like this crypto or buffer or util, it would have been able to transpile our code into something where we'd have a file that was built that we could load directly into the browser.

[00:02:16] So again, the goal here is to take your common JS formatted modules, the ones that we're writing, there for node and to package those so that they can be loaded. So you have a different version of the file that can be loaded directly into the browser. Okay, another thing to tell you about, [COUGH] kind of in a similar vein.

[00:02:36] What if you wanted to write a module that, or a piece of code, and you wanted it to run in both the browser and on the server, and you also wanted it to be able to be loadable by an AMD loader? And what if you didn't need any of that transpilation stuff that Browserify provides, is there some way?

[00:02:58] Cuz when we look at helloworld3, the way it's using module.exports, well, that doesn't work if we load that into the browser because there isn't a module.exports in the browser. And that's not gonna work for AMD cuz AMD uses a different syntax for it. So is there a way to do it, and a while back, there was this project that came out called the UMD, the universal module definition.

[00:03:22] It was an attempt, not that there was only one way, but it was an attempt to come up with patterns, where we could create a module definition that would work in a variety of circumstances. That is the way that they were loaded. So I've provided for you in your directory, you should find a file [COUGH] called umdshell.js.

[00:03:46] It's just an example file, it doesn't do anything, but I want you to open up umdshell.js, and I'll explain to you. This is a modified version of one of the forms of UMD, and the main thing that you would do here is you need to make sure they're on line 5 right there.

[00:04:03] At the beginning of line 5, you would wanna give your module like a real name because that's the name that's gonna get bound if you load it into a browser. That's gonna be the global name for your module. It's also gonna be the name that it's referred to if it's being loaded into AMD or something like that.

[00:04:18] So you wanna make sure you give it some sort of reasonable name. But inside of these two curly braces where you see here, you would write your module exactly like I taught you yesterday. You'd put your functions and your variables privately and all of that stuff. You'd return back some sort of object, and you could name it like I do if you needed to, but you just simply do modules the way we did if you based modules yesterday.

[00:04:41] And what this will do, this particular piece of code, the way it runs, is you'll note that it is up here, it's already looking for which environment is it running in. It checks to see if it's in node by looking for a module.exports, and if it is, it runs it in a way that works for node.

[00:04:59] And if you're in AMD, it runs it in a way that works for AMD. And if you are, instead, in the browser, it goes ahead and adds a global into the browser and calls your definition function the way you want. So this universal format, if you will, quote unquote universal format, allows the same module based code to be run in each of these three different sort of loading scenarios.

[00:05:24] As an example of that, if I were to open up, if I go into node_modules and I go into asynquence and you look at the asq.source JavaScript file, you'll note that I use the UMD pattern for my asynquence lib. The reason for that is I don't rely upon any dependencies whatsoever, but I do want for you to be able to load asynquence, both in the browser and in node and in AMD.

[00:05:53] So I use this UMD format, and I don't need you to do any kind of building or transpiling. It's just a format that will automatically work in all three of those loading scenarios. So that's another option if you're trying to build yourself a module that people can use in multiple different loading scenarios.

[00:06:09] You might think about using the UMD format, kind of wrapped around your module definitions.