Global variable not working in NodeJS

Wouter Florijn picture Wouter Florijn · Jan 5, 2017 · Viewed 8.5k times · Source

I am trying to get global variables working in node.js, but it seems like I don't really understand the concept, even though my understanding matches the documentation.

Minimal example

My main.js file, which is compiled using rollup is:

global.a = 1;
require('./core/test.js');

My core/test.js file is simply:

console.log(a);

This causes the error:

Uncaught ReferenceError: a is not defined

The fully compiled output is:

(function (exports) {
'use strict';

var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

console.log(a);

commonjsGlobal.a = 1;

}((this.LaravelElixirBundle = this.LaravelElixirBundle || {})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjpudWxsLCJzb3VyY2VzIjpbIkM6L3dhbXAvd3d3L3V1YmMvcmVzb3VyY2VzL2Fzc2V0cy9qcy9jb3JlL3Rlc3QuanMiLCJDOi93YW1wL3d3dy91dWJjL3Jlc291cmNlcy9hc3NldHMvanMvYXBwLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnNvbGUubG9nKGEpO1xyXG4iLCJnbG9iYWwuYSA9IDE7XHJcbnJlcXVpcmUoJy4vY29yZS90ZXN0LmpzJyk7XHJcbiJdLCJuYW1lcyI6WyJnbG9iYWwiXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQzs7QUNBZkEsY0FBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7OyJ9

It seems that a gets defined after console.log(a);. I'm not 100% sure if this matters in JS but it could be causing the error.

So my question is: what causes this, and what am I doing wrong here?

Possibly relevant information: I'm using Laravel Elixir to compile everything.

Note: Please don't post discussion on whether or not to use global variables in node.js or in general. I know it's usually a bad idea, but I have a very good reason to do it in this case.

Edit: Additional context

What I'm really trying to do is getting Zurb Foundation to work with Laravel Elixir though node.js. I installed foundation-sites through NPM. foundation-sites relies on jquery, which it pulls in itself. However, Foundation doesn't seem to follow the usual conventions of just using something like var jquery = require('jquery'); in its own js file. It actually relies upon a global jQuery variable being available. Therefore I have to ensure that somehow.

My actual file looks like this:

global.jQuery = global.$ = require('jquery');
require('foundation-sites');

So if there are any Foundation/Laravel-specific anwers I would be very happy to hear them as well. Is there something I'm not getting, or did Foundation just not create their package the "right" way?

Answer

T.J. Crowder picture T.J. Crowder · Jan 5, 2017

It looks to me like an issue with your bundler not respecting the order you're doing those two lines in. Your source is clearly:

global.a = 1;
require('./core/test.js');

...but the bundled result is clearly the other way around:

console.log(a);
commonjsGlobal.a = 1;

It seems like it's hoisting the require calls. In general, having require calls that need to be done at a particular point in the execution control flow is not best practice (in fact, when defining modules for ES2015, import is explicitly defined as not being executed in the module's step-by-step control flow).

So if you need to do this, you'll probably want to look at another bundler. But check that it supports order other than dependency resolution order.