Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS - Requiring module returns empty array

Tags:

node.js

Writing the simplest module we could, we write into hello.js:

var hello = function(){
  console.log('hello');
};

exports = hello; \\ Doesn't work on Amazon EC2 Ubuntu Instance nor Windows Powershell

I run Node and require the module

var hello = require('./hello');
hello;

and an empty array {} gets returned when I'm supposed to get [Function].

I tried replacing exports with module.exports, but this doesn't work on my Windows Powershell. It does work on my Amazon EC2 Ubuntu Instance, so why doesn't exports work? Has the API changed? And what could possibly be happening with Powershell that neither of these work?

I know Windows isn't the most desirable development environment, but I can't get my head around such a simple mishap.

like image 535
ergo Avatar asked Mar 14 '13 14:03

ergo


2 Answers

EDIT

exporting with ES6 is a little nicer

export const hello = function(){
  console.log('hello');
};

importing will look like

import {hello} from './file';

Original answer

You'll want to use module.exports

var hello = function(){
  console.log('hello');
};

module.exports = hello;

If just exporting one thing, I'll usually do it all in one line

var hello = module.exports = function() {
  console.log('hello');
};

Extras

If you use a named function, in the event an error occurs in your code, your stack trace will look a lot nicer. Here's the way I would write it

// use a named function               ↓
var hello = module.exports = function hello() {
  console.log("hello");
};

Now instead of showing anonymous for the function name in the stack trace, it will show you hello. This makes finding bugs so much easier.

I use this pattern everywhere so that I can debug code easily. Here's another example

// event listeners          ↓
mystream.on("end", function onEnd() {
  console.log("mystream ended");
};

// callbacks                              ↓
Pokemon.where({name: "Metapod"}, function pokemonWhere(err, result) {
  // do stuff
});

If you want to export multiple things, you can use exports directly, but you must provide a key

// lib/foobar.js
exports.foo = function foo() {
  console.log("hello foo!");
};

exports.bar = function bar() {
  console.log("hello bar!");
};

Now when you use that file

var foobar = require("./lib/foobar");

foobar.foo(); // hello foo!
foobar.bar(); // hello bar!

As a final bonus, I'll show you how you can rewrite that foobar.js by exporting a single object but still getting the same behavior

// lib/foobar.js
module.exports = {
  foo: function foo() {
    console.log("hello foo!");
  },
  bar: function bar() {
    console.log("hello bar!");
  }
};

// works the same as before!

This allows you to write modules in whichever way is best suited for that particular module. Yay!

like image 82
Mulan Avatar answered Nov 18 '22 17:11

Mulan


The reason exports is not working is because of the reference conflict. The top variable in each file is module which has a property module.exports. When the module is loaded new variable is created in the background. Something like this happens:

var exports = module.exports;

Obviously exports is a reference to module.exports, but doing

exports = function(){};

forces exports variable to point at function object - it does not change module.exports. It's like doing:

var TEST = { foo: 1 };
var foo = TEST.foo;
foo = "bar";
console.log(TEST.foo);
// 1

Common practice is to do:

module.exports = exports = function() { ... };

I have no idea why it doesn't work under Windows Powershell. To be honest I'm not even sure what that is. :) Can't you just use native command prompt?

like image 34
freakish Avatar answered Nov 18 '22 17:11

freakish