4

I see this in many JS libraries out there, mostly looking through GitHub, currently looking at PeerJS. I'm referring to this:

var util = require('./util');
var EventEmitter = require('eventemitter3');
var Negotiator = require('./negotiator');
var Reliable = require('reliable');
...
window.Socket = require('./socket');
window.MediaConnection = require('./mediaconnection');
window.DataConnection = require('./dataconnection');
window.Peer = require('./peer');
window.RTCPeerConnection = require('./adapter').RTCPeerConnection;
window.RTCSessionDescription = require('./adapter').RTCSessionDescription;
window.RTCIceCandidate = require('./adapter').RTCIceCandidate;
window.Negotiator = require('./negotiator');
window.BinaryPack = require('js-binarypack');
...

Just from intuition, it seems like require() is importing/including whatever is being passed in, i.e., EventEmitter. However, I can't figure out where require() is coming from?

I'm not too familiar with NodeJS, and this seems like it's a NodeJS thing, but I don't understand how require() fits into a web browser context, where NodeJS doesn't exist.

I've seen RequireJS and Browserify, but these are libraries that would need to be included with application in order to use the require() function. In the example of PeerJS, I can just include it:

<script type="text/javascript" src="/static/js/peerjs.v0.3.13.js"></script>

... and it uses require() no problem. However, it doesn't look like there's any 3rd party libraries that are defining require() that are being bundled along with the PeerJS source code.

How is it being included? How is it being initialized? How is it fetching whatever is being passed in, i.e., "EventEmitter"?

Hristo
  • 45,559
  • 65
  • 163
  • 230
  • http://requirejs.org/ explains itself – PM 77-1 Apr 08 '15 at 03:34
  • @PM77-1: PeerJS does not use the RequireJS library. – Qantas 94 Heavy Apr 08 '15 at 03:38
  • thanks @Qantas94Heavy. it doesn't seem like RequireJS is being used here – Hristo Apr 08 '15 at 03:40
  • PeerJS uses Browserify to bundle the scripts together, the `require` function is defined as a function parameter in the first line of the built code. https://github.com/peers/peerjs/blob/cf5be327ae20df97e21ac9ba91838deafcbeeb7e/dist/peer.js#L1 – Qantas 94 Heavy Apr 08 '15 at 03:44
  • You can also see this from the Gruntfile.js, which is used to specify how the file is built. https://github.com/peers/peerjs/blob/cf5be327ae20df97e21ac9ba91838deafcbeeb7e/Gruntfile.js#L40 – Qantas 94 Heavy Apr 08 '15 at 03:49
  • ahhh I see what's going on now. thanks @Qantas94Heavy! why don't you put that down as an answer so you can get credit? – Hristo Apr 08 '15 at 03:50
  • Sorry for VTCing, I thought this was a more general question about what `require` does rather than where it was coming from. – Qantas 94 Heavy Apr 08 '15 at 03:54
  • no problem. I can understand why that's what you'd have thought. suggestions on how to reword the question to avoid confusion? – Hristo Apr 08 '15 at 03:56

1 Answers1

4

It's a way to include external JavaScript (or really any other file) into your script through a single point of entry without introducing globals. It's most often used with Asynchronous Module Definition (AMD) and CommonJS modules. At it's highest level, require() is an API to use JavaScript modules. NodeJS uses the CommonJS syntax for the most part.

There's also no definite "better" one to use. It becomes almost an East Coast/West Coast turf war trying to discuss one vs the other. Some say that AMD modules are too verbose since you have to capture all of your imports in a closure and then use them which means you have to look in two different places for where you are defining your variables and imports:

AMD from RequireJS also Dojo

define('myModule', ['dep1', 'dep2'], function (dep1, dep2) {
    return function () {};
});

CommonJS

var foobar = require('./foobar').foobar,
    test   = new foobar();

test.bar(); // 'Hello bar'

Additionally, some say that the A part of AMD doesn't really benefit you often enough to be worth the overhead.

Where does the "require" part come from?

In the browser, the require() comes from whatever library you are loading whether it be an AMD or CommonJS loader. However, for your above examples, you look like you're using it in a NodeJS context. NodeJS has the require() defined within the environment just like module.exports. In fact, the module.exports is what is given to whatever variable you're assigning to with the require(...).

Contrast the module.exports from CommonJS to how AMD gets your module into your variable's hands which is just the return from the closure that you put in a call to define().

Can these be used together?

One other thing to touch on is that they aren't exclusive to one another. They can be coerced into playing with one another either using some kind of wrapper or by using another convention: UMD. UMD tries to let you create modules that work no matter the environment exposing your module through whatever convention is available be it module.exports or define().

zero298
  • 25,467
  • 10
  • 75
  • 100
  • but where is it implemented? it doesn't seem to be a browser API; typing in `require` in the console doesn't do anything... – Hristo Apr 08 '15 at 03:42
  • I'm not using it in a NodeJS context. I'm just including the PeerJS library in my web app. From one of the comments, it looks like PeerJS is using browserify... – Hristo Apr 08 '15 at 03:49
  • @Hristo How do you build your webapp? If this is using `browserify` then it is most likely going through some build step that still uses `nodejs` be it a `gulpfile`, `gruntfile`, `npm build` call, or some other magic. – zero298 Apr 08 '15 at 04:00
  • it's not about how I build my webapp, it's about how PeerJS packages their library. looks like they use `grunt.js` and `browserify` – Hristo Apr 08 '15 at 04:02