简体   繁体   中英

Global variable not working in NodeJS

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?

You are right that it should work. Here's a working example:

// file1.js
global.a = 'hello';
require('./file2');

// file2.js
console.log(a);

Run node file1.js , and you'll see 'hello' printed to the console.

It looks like you've got some other tool being used (Laravel / Elixir). Use node directly and see what happens.

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.

Alright I solved this in a pretty simple way, by using browserify instead of rollup . Thanks for the other answers pointing me in the right direction. It's not a perfect solution, and I still don't fully understand what the differences are between the two, but it'll do for this project.

The relevant part of my gulpfile:

mix.browserify('app.js','public/js/app.js');

To use browserify with Laravel Elixir, I used

npm install laravel-elixir-browserify-official --save-dev

I solved this for rollup by providing an output.intro that sets up the required variables. In your case this would be:

// rollup.config.js
export default {
  // ...
  output: {
    // ...
    intro: `let a = 1;`
  }
};

Admittedly this qualifies as a hack, but solves the bundling problem in my case (where switching away from rollup is not an option).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM