Reputation: 2941
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.
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.
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?
Upvotes: 3
Views: 15772
Reputation: 1
Same problem, only when using import
. Solved the problem this way:
// main.js
import './globals.js';
import './file.js';
// globals.js
global.a = 123;
// file.js
console.log(a);
Upvotes: 0
Reputation: 3507
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).
Upvotes: 0
Reputation: 2941
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
Upvotes: 0
Reputation: 1074276
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.
Upvotes: 4
Reputation: 4551
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.
Upvotes: 3