Is there way to define global variable which will be available inside some module.
So, if we have module test, and inside test we have files index.js, test1.js, test2.js, can we define variable inside index.js to be available in test1.js and test2.js, but not outside this module?
Exact situation:
So, I am using some npm module and I don't want to require that module every time, but only within one directory, not whole node application, because that can cause problems to me.
test1.js:
exports = test1Module = {
func1: function(...){...},
func2: function(...){...},
func3: function(...){ console.log(test1Module.secretVariable); }
}
index.js:
var secretVariable = "secretValue";
var test1 = require('test1');
test1.secretVariable = secretVariable;
And similarly with test2, but NOT test3..
What you are looking for is namespaces.
Take a look at the following
How do I declare a namespace in JavaScript?
var yourNamespace = {
foo: function() {
},
bar: function() {
}
};
...
yourNamespace.foo();
Related
When testing with Mocha, how dose one load foo.js so that the foo-test.js can test global variables such as giveMeFive()?
foo.js:
function giveMeFive() {
return 'High five!');
}
foo-test.js:
describe('#convertNumberToDollar()', function() {
it('should get a successful high five', () => {
assert.ok( giveMeFive() === 'High five!', ' successful high five.' );
});
});
It would be ideal if the solution can be automated via Bamboo.
You can just use import * as thisNameDoesntMatter from 'foo' or, using es5 style (which is cleaner in this case), require('foo') and globals defined in that file will be available on the global scope.
For instance, if you define the following JavaScript file:
//test.js
aGlobalVariable = 'someValue';
let aLocalVariable = 'anotherValue';
export default aLocalVariable;
This is the code Babel will generate (using the es2015 preset and the "node" environment):
//test-compiled.js
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
global.aGlobalVariable = 'someValue';
var aLocalVariable = 'anotherValue';
exports.default = aLocalVariable;
As you can see, the aGlobalVariable declaration is kept in the module. As the entire compiled file will be evaluated when it's imported, aGlobalVariable will be available on the global scope whenever you import this module (if you chose the "browser" environment, it would be defined on window). You don't need to explicitly request the globals to be imported.
I'm using webpack commmon chuncks to define a global library object (common components) that will be used in common with other generated bundles.
Common code (components.js)
MyLib = window.MayLib = {}
MyLib.Utils = {
commonFn : function (){
/* common code */
}
}
module.exports = MayLib;
First common usage (dashboard.js)
require.ensure ('./components', function () {
MyLib.Dashboard = {
/** Dashboad code here */
}
})
second common usage (account.js)
require.ensure ('./components', function (){
MyLib.Account = {
/** Account code here */
}
})
After generate bundles, a new common code has been created but MyLib is undefined in global window, "cannot set property of undefined"
You can solve your problem using the expose-loader. See also this similar issue.
Although i think you can easily solve your problem by requiring the MyLib object inside the callback. No need to expose it to global scope anymore.
require.ensure ('./components', function (require){
var MyLib = require('./components');
MyLib.Account = {
/** Account code here */
}
})
Sidenote: You can try to simplify your code-splitting by using the CommonsChunkPlugin, then you just use simple require('components') and the plugin is doing the rest.
I am writing some logic in fileB.js that needs to call another function declared in fileA.js. fileA.js declares a function called abc(). How can I call abc() from fileB.js.
Both fileA and fileB are in the same directory.
Thank you
Ps. I am not using this with HTML. I am just running it locally as part of another project I am working on. I am now using node to run it from terminal. But I am not using anything else in these two files. I just have a bunch of really simple functions. No node.js modules or anything...
Node.js isolates each file as a module, giving each their own local scope to define essentially "private" functions and vars.
With this isolation, fileA will need to export abc in order to share it with other files/modules:
function abc() {
// ...
}
exports.abc = abc;
Then, fileB can require() fileA with a relative path (. referring to the current directory) and use its exported function:
var a = require('./fileA');
a.abc();
If you are using node, then in fileA:
module.exports = { abc: abc } //assuming that abc holds a reference to your function, declared somewhere above
Then, in fileB you require fileA and use what you exported:
var fileA = require('./fileA.js');
fileA.abc();
Since you're running it in NodeJS, I'd suggest doing the following at the top of fileB.js:
var fileA = require( './fileA.js' );
However, in order for this to work, the functions you want to use in fileB.js should be exported from fileA.js. To do this, lets assume that the function abc() is what you want to access:
// In fileA.js:
function abc() {
// ... do something ...
}
module.exports = abc;
If you want multiple functions/variables/objects available to fileB.js, you can export them all as one object:
// In fileA.js
function abc() {
// ... do something here ...
}
var myObject = {
propOne: 'foo',
propTwo: 'bar
};
module.exports = {
abc: abc,
myObject: myObject
};
Then, within fileB.js:
// Import the fileA object you just created.
var fileA = require( './fileA.js' );
// Save references to abc and myObject
var myObject = fileA.myObject,
abc = fileA.abc;
Just include both the JS files in the HTML and then simply call them any function anywhere, it will work.
I'm considering adopting browserify for some of my projects, but would like to make sure that others don't have to use browserify if they want to use the (bundled) code. The obvious way to do this is to both expose the modules exports through module.exports as well as through a window. global. However, I'd rather not pollute the global namespace for those who are requireing the script.
Is it possible to detect if a script is being required? If it is, then I could do something like:
var mymodule = (function() { ... })();
if (isRequired()) {
module.exports = mymodule;
} else {
window.mymodule = mymodule;
}
Note that no matter what, this will be bundled beforehand, so the var mymodule won't be exposing a global. Also, currently I'm using the revealing module pattern, but would be willing to switch to something more appropriate for browserify.
What's the best way to make a module both requireable and <script src=able? Is it best to just expose a global in both circumstances?
There is a good article from Forbes Lindesay explaining how to do standalone builds:
http://www.forbeslindesay.co.uk/post/46324645400/standalone-browserify-builds
The short version, use the standalone option:
browserify beep.js --standalone beep-boop > bundle.js
I'm dealing with the same problem building a library and here is a rought opinion. I think we need to separate first the audiences for a library in few categories:
those who use browserify and NPM
those who will just download a mylib.min.js and use one way or another
AMD (with bower?), might be the third category.
So, for 1 it is easy, you will have a your index.js module:
module.exports = function () { /* code */ }
and your package.json will have a main
"main": "index.js"
Notice I haven't add any window.xx code to index.js.
For 2 I think the best idea is to create a standalone.js
var mylib = require('./index.js');
global.window.mylib = mylib;
This is what browserify should build.
For 3 (if you care about) you can tweak standalone.js as follows:
var mylib = require('./index.js');
if (typeof global.window.define == 'function' && global.window.define.amd) {
global.window.define('mylib', function () { return mylib; });
} else {
global.window.mylib = mylib;
}
Assuming another library hasn't created a global module.exports object, you can simply check for the existence of module.exports
var mymodule = (function() { ... })();
if (module && module.exports) {
module.exports = mymodule;
} else {
window.mymodule = mymodule;
}
Why not just wrap the entire thing with a closure and pass exports as a parameter?
(function (exports) {
// code here
// ...
exports.foo = bar;
})(exports || this);
This way it will also export it to WebWorker scope and other 'windowless' environments.
Looking at a random source file of the express framework for NodeJS, there are two lines of the code that I do not understand (these lines of code are typical of almost all NodeJS files).
/**
* Expose `Router` constructor.
*/
exports = module.exports = Router;
and
/**
* Expose HTTP methods.
*/
var methods = exports.methods = require('./methods');
I understand that the first piece of code allows the rest of the functions in the file to be exposed to the NodeJS app, but I don't understand exactly how it works, or what the code in the line means.
What do exports and module.exports actually mean?
I believe the 2nd piece of code allows the functions in the file to access methods, but again, how exactly does it do this.
Basically, what are these magic words: module and exports?
To be more specific:
module is the global scope variable inside a file.
So if you call require("foo") then :
// foo.js
console.log(this === module); // true
It acts in the same way that window acts in the browser.
There is also another global object called global which you can write and read from in any file you want, but that involves mutating global scope and this is EVIL
exports is a variable that lives on module.exports. It's basically what you export when a file is required.
// foo.js
module.exports = 42;
// main.js
console.log(require("foo") === 42); // true
There is a minor problem with exports on it's own. The _global scope context+ and module are not the same. (In the browser the global scope context and window are the same).
// foo.js
var exports = {}; // creates a new local variable called exports, and conflicts with
// living on module.exports
exports = {}; // does the same as above
module.exports = {}; // just works because its the "correct" exports
// bar.js
exports.foo = 42; // this does not create a new exports variable so it just works
Read more about exports
To expand on Raynos's answer...
exports is basically an alias for module.exports - I recommend just not using it. You can expose methods and properties from a module by setting them on module.exports, as follows:
//file 'module1.js'
module.exports.foo = function () { return 'bar' }
module.exports.baz = 5
Then you get access to it in your code:
var module1 = require('module1')
console.log(module1.foo())
console.log(module1.baz)
You can also override module.exports entirely to simply provide a single object upon require:
//glorp.js
module.exports = function () {
this.foo = function () { return 'bar' }
this.baz = 5
return this // need to return `this` object here
}
Now you've got a nice prototype:
var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz)
There are myriad other ways to play with module.exports and require. Just remember, require('foo') always returns the same instance even if you call it multiple times.
Note
For the following to work,
var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz)
this has to be returned in the function that is assigned to module.exports. Otherwise, you'll get a TypeError:
console.log(g1.foo())
^
TypeError: Cannot read property 'foo' of undefined
You can find the best answer in node.js source code.
If someone is requiring your js module,
your script turns into a function by node as follows (see src/node.js).
// require function does this..
(function (exports, require, module, __filename, __dirname) {
... your javascript contents...
});
Node will wrap your script. Then above script will be executed as follows:
//module.js
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);
So in your script,
exports is just module.exports.
In your script, you can add something to this exports object (functions..).
require function will return this object. This is node.js's module system (commonJS specification).
But be careful not to modify module.exports. Otherwise your current exports will be meaningless.
module is an object that represents what that particular source file would like to publicly expose. Instead of having something akin to header files in the c/c++ world, you describe what the module exports by defining this object. the node runtime then uses this object to determine what about your module is 'public.'
its a similar concept to exporting functions from a dll in the compiled world. you have to define explicitly what functions can be accessed by the outside world. this helps with encapsulation and lets your organize your libraries in a clean way.
Module's code is wrapped in module.exports (The module, maybe composed by other module).
There are many ways to build a module, but this is one very common (and my personal favorite).
// Dependencies
// const module = require('module');
// Module object
var foo = {}
// Internal property
foo._a = 'a';
// "Public" property
foo.b = 'b';
// Method
foo.fu = function() { return 'fu' };
// Export
module.exports = foo;