Are node modules run when they are required?
For example: You have a file foo.js that contains some code and some exports.
When I import the file by running the following code
var foo = require(./foo.js);
is all the code inside the file foo.js run and only exported after that?
Much like in a browser's <script>, as soon as you require a module the code is parsed and executed.
However, depending on how the module's code is structured, there may be no function calls.
For example:
// my-module-1.js
// This one only defines a function.
// Nothing happens until you call it.
function doSomething () {
// body
}
module.exports = doSomething;
// my-module-2.js
// This one will actually call the anonymous
// function as soon as you `require` it.
(function () {
// body
})();
Some examples..
'use strict';
var a = 2 * 4; //this is executed when require called
console.log('required'); //so is this..
function doSomething() {}; //this is just parsed
module.exports = doSomething; //this is placed on the exports, but still not executed..
Only in the sense that any other JS code is run when loaded.
e.g. a function definition in the main body of the module will be run and create a function, but that function won't be called until some other code actually calls it.
Before exporting the content that are visible outside of your module, if there is same code that can be execute it it execute but the content that are export like a class will be execute in the code that import it.
For example, if I have this code
console.log("foo.js")
module.exports = {
Person: function(){}
}
the console.log will be execute when you require it.
Related
If two .js files having functions with the same name and parameter but the code is different. What will happen after bundling using bundle.config?
Which one will call?
Or/And how can we fix that?
//in parent.js file
function getdetails(id)
{
//enter code here
}
//in student.js file
function getdetails(id)
{
//enter code here
}
Depending on the type of bundler, normally functions are scoped from the modules they are exported from.
So for example:
//in parent.js file
function getdetails(id)
{
//enter code here
}
//in student.js file
function getdetails(id)
{
//enter code here
}
In the bundled javascript, they become (as an general example):
_parent.getdetails()
_student.getdetails()
You could check your un-minified bundled code and search for getdetails to see how the functions are being scoped for clarification.
Side note
If two functions are being defined with the same name, in the same scope (which shouldn't be the case here), then the function re-defined each time.
//in parent.js file
function getdetails() {console.log("foo");}
function getdetails() {console.log("bar");}
getdetails(); // Outputs "bar"
My directory structure is as follows:
src
|--> js
|--> more js files in nested folders
test
|--> spec
|--> js test files
If within one of my js tests in spec, if I try and call a function from a js file within my nested src directories, I can call the function fine. However, if I try and call a variable, it cannot find it, and I get a Reference Error.
My function (which is visible) is declared like so:
function myFunctionName() {
... some code ...
}
My variable is declared after the function, and not inside any other function, like so:
var myVar = '...';
I've also tried declaring myVar as a const, for the same result.
In myTestSpec.js
(function () {
'use strict';
describe('...', function() {
it('...', function () {
// Works
expect(myFunctionName()).toEqual('...');
// Doesn't work
var newVar = myVar;
});
});
})();
Ended up solving this by just sticking any 'global' state I required into a function, to be returned as json. I now just need to call this function everytime I start a test.
This has a slight performance hit I guess as we need to recreate the state across multiple tests, however it's not production code (test only) so shouldn't be an issue, and it means I don't have to depend on another JS library such as require js..
I'm really just wondering if this is the "right" way to do things, or if I'm missing something about modules; we don't use node, just browser, but maybe this is applicable to both. In page.js we have a function world() that we need a module (module.js) to be able to call. Exporting world() and importing it into module doesn't seem like the appropriate way to do things.
Why not? page.js is js that is only applicable to one html page (page.html); world() manipulates some specific UI elements on page.html, and isn't going to ever be reused anywhere else. Module.js does some ajax/server related work; this is done on a lot of other html pages, so of course we make it a module for easy reuse.
init() is the real entry point. Contrived example:
page.js
import mod from 'module.js'
function init() {
hello(); // print 'hello' to console
const options = {
// pass the 'world' function to module.js
functionParam: world,
// some other irrelevant options here
};
mod.print(options); // print 'world' to console
}
function hello() {
console.log('hello');
}
function world() {
console.log('world');
}
module.js
function print(options) {
// should call the world function, we should see 'world' logged to console
options.functionParam();
}
export default print;
Running require(['pages/home']) will work once but if I use require(['pages/home']) again then it won't run.
The module "pages/home" is a file named "home.js" in a directory named "pages".
main.js
require(['pages/home']);
pages/home.js
define('pages/home', function() {
console.log('running pages/home module');
});
RequireJS modules are singletons. It loads a module once and only once. If a module has been loaded already, what you get if you load it again is a reference to the same module as originally loaded. The factory function you pass to define won't be run a second time.
So what you are seeing is exactly what is expected.
Static code in modules isn't supposed to be evaluated more than once, just like a script loaded through a normal <script> tag won't be run more than once during the page load.
Imagine if a module contained code like:
define('my-module', function () {
var foo = foo || 0;
var bar = ++foo;
});
You should expect bar and foo to both === 1, but if the module was run repeatedly and a global foo existed, that may not be the case. Admittedly, this is a very contrived example, but evaluating a module repeatedly could cause serious problems.
Make it return a function/object that can be executed after you require it.
define('pages/home', function() {
return function(){
console.log('running pages/home module');
};
});
require(['pages/home'], function(resultFunc){
window.YourFunc = resultFunc;
});
Now you can execute your function whenever you want
My javascript project looks like this (Example A)
;(function (window, document, undefined) {
var func1 = function () {
// some code
};
var func2 = function () {
// some code
};
// ... some more functions
// lines of main code
// ...
})(window, document);
I want to place func1, func2, ..., code in separate files to make code like this (Example B):
;(function (window, document, undefined) {
var func1 = require ("func1.js");
var func2 = require ("func2.js");
// ... more requires
// lines of main code
// ...
})(window, document);
…and then somehow compile it to get the code as in Example A
Is there any particular way to do this? I tried to use require.js (r.js), but i've got require and define statements in compiled code (so I need require.js to run compiled code in browser). Is it possible to get flat static js-file without any dependencies with r.js? Maybe there is another way to do this? Thanx
Depending on how your code works, you can always just go cat *.js > all.js then run a minifier or something on it.