How to properly require files into another file - node.js

I have a bunch of js script files that use require to require the same series of libraries, etc.'
let path = require('path');
let _ = require('underscore');
I want to put all these requirements into a separate library file that I can then reuse amongst the files that need them. I though I could do something like this:
var common = function() {
this.requireFiles = function() {
let path = require('path');
let _ = require('underscore');
...
}
};
export.common = common;
However, when I want to include this library in those files that use all these same files, it does not work. I am trying something like this:
let CommonTools = require('../server_libs/commonFiles').common;
let commonFiles = new CommonTools();
migration.requireFiles();
This give me an error that _ is not a function, when I want to use the underscore methods. Any hints as to where I should look for better understanding on this topic?

I personally do not recommend making a common module. The node.js module mentality is to just require() in what a module needs. Yes, it seems like a little extra/redundant typing in each module, but it makes each module self describing and does not build any unnecessary dependencies between modules leading to the simplest module sharing or reuse options. Modules are cached by the require() sub-system so it doesn't really cost you at runtime to just require() in each module as you need them. This is pretty much the node.js way.
That said, if you really want to make a common module, you can do it like this:
common.js
module.exports = {
_: require('underscore');
path: require('path');
}
otherModule.js
const {_, path} = require('common.js');
// can now call underscore methods _.each()
// can now call path methods path.join()
This uses destructing assignment to get properties from the common.js exports and assign them to a module-scoped variable and to do it for multiple properties in one statement. It still requires you to list each property you want defined in this module (which helps self describe what you're doing).
This also assume you're using require() and module.exports. If you're using the newer import and export keywords, then you can modify the syntax accordingly, but still use the same concept.

Related

How do I use require inside a module with the parents context?

app.js
require('./modules/mod');
modules/mod/mod.js
modules.exports = () => {
require('./modules/secondmodule');
}
Essentially I want the above code to be able to require modules, but using the same context that itself was called from, e.g. another module in the same folder, without having to use relative paths.
I thought module.require() did this, but it seems to give me the same error that require() was after I moved my code into the separate module (mod.js).
edit:
I have since discovered I can use require.parent.module and it seems to be working. Please let me know if this is not advised.
require uses paths that are relative to current module. It's possible to do this by providing require from parent module:
modules.exports = parentRequire => {
parentRequire('./modules/secondmodule');
}
Which is used like:
require('./modules/mod')(require);
It's correct to use relative modules instead because child module shouldn't be aware of the context in which it's evaluated:
require('../secondmodule');
In case mod has to be decoupled from secondmodule, dependencies can be provided to it with some common pattern, e.g. dependency injection or service locator.
Secondary optional answer:
module.exports = () => {
module.parent.require('./modules/secondmodule');
}

Node.js dynamic relative require path

I need to be able to use require() on a dynamic relative path - meaning that the relative path needs to change depending on the current environment.
What is the best practice for this type of situation?
I thought of something like this:
var module = require(process.env.MY_MODULES_PATH + '/my-module');
However environment variables are not very convenient.
Are there other possibilities?
Maybe use package.json post-install script to set the environment variable for me?
Maybe there's a built in solution in node I don't know about?
EDIT
I just realized that this is a special case of require() "mocking". Is there a best practice for how to mock require() for unit-tests for example?
MockedRequire.js
var path = require('path');
function MockedRequire(module) {
return require(path.join('/path/to/modules', module));
}
module.exports = MockedRequire;
Use:
var mymodule = require('./MockedRequire.js')('mymodule');
To be honest I haven't actually tested this but it should work without issues.
Webpack needs to know what files to bundle at compile time, but expression only be given value in runtime, you need require.context:
/* If structure like:
src -
|
-- index.js (where these code deploy)
|
-- assets -
|
--img
*/
let assetsPath = require.context('./assets/img', false, /\.(png|jpe?g|svg)$/);
// See where is the image after bundling.
// console.log(assetsPath('./MyImage.png'));
// In fact you could put all the images you want in './assets/img', and access it by index: './otherImg.jpg'
var newelement = {
"id": doc.id,
"background": assetsPath('./MyImage.png');
};
I would suggest using a configuration loader. It will select your path based on your NODE_ENV variable, but its much cleaner than what you suggested because you keep all of the environment specific config within a single external file.
Examples:
https://github.com/uber/zero-config
https://github.com/vngrs/konfig
Roll your own

Require a file within itself in node.js

How do you require a file within itself in node.js? E.g. api.js:
var api = require(./api.js);
What is the best practice for doing this?
You can totally do it. Try this, for instance (in a file named a.js):
exports.foo = 'foo';
var a = require('./a');
console.log(a);
exports.bar = 'bar';
console.log(a);
At the point where require executes, it will return the module a as it exists at the point where require runs so the field foo will be defined but not bar.
There's no point to doing this though. You use require to bring into your current scope an object which would otherwise not be available (namely, a module). But you don't need to do this to access the module you are currently in: it is already fully available.
The code above works because Node has rules to handle cyclic dependencies. And here you have a module which is cyclicly dependent on itself. Rather than go into an infinite loop of requires, Node has require return the module as built up to that point: a partial module. And the modules in a cyclic dependency have to be designed to handle the fact that they may get partial modules.
Cyclic dependencies are to be avoided as much as possible. Most of the time this means refactoring the modules to avoid the mutual dependency by moving functionality into one or more new modules.
So, again, the best practice is to not do this in the first place.

Making modules global for use in other files in node.js

I read in another question that i can not find now that it was a bad idea to make modules in node.js global, then he changed his answer because of changes in node.js
The examples for express.js on github does now show an example.
https://github.com/visionmedia/express/tree/master/examples
So what if i need the same module in multiple files, like sequelize or async?
app.js:
var document = require('./routes/document')
async = require('async');
/routes/document.js:
async.series([...]);
OR
app.js:
var document = require('./routes/document')
var async = require('async');
/routes/document.js:
var async = require('async');
async.series([...]);
Should i require the async module again in document.js, or just make async global so that i can use it without require it in new files?
Do not use globals to access modules. Always use require and only require() the modules you need in that .js file. Require will only load your module once and hold a reference to it.
Only requiring what you need, even if it's several modules, is good because it makes it clear what the dependencies of your code are and might help you restructure your code later.
Only requiring() what you need can also help at the point where you want to replace one module with another. For example, you might want to replace knox(S3) with the new aws-sdk module. When you remove the knox npm module, require will immediately blow up in the files that use/require knox. If it was a global variable, you would need to find all references to that global reference and rely on your IDE or text editor to find it.
In short, include it in each file. The file is cached after the first require, so the content is really only run once (you can test this by putting a log statement in the require; it'll only show once).
What I do is make one file which requires all the others I need, and exports them all. Then you only need to require the one file. This can be really handy when you have many modules that you're including.
There is nothing wrong with requiring a module more than once. Internally require only executes the required file once and then caches the result. See the Node.js Modules documentation for more information.

nodejs module does not export function

I ran into an issue with my Nodejs application.
I have two different apps that are using shared library, which is located so that it is found one level up in node_modules. So i have this structure ./app1/app.js, ./app2/app.js and ./node_modules/shared.libs/index.js.
shared.libs in its turn has some other modules installed, like mongoose, redis etc. Plus some mogoose models with additional functions in them. All are exported from index.js like this:
exports.async = require('async');
exports.config = require('./config');
exports.utils = require('./lib/utils');
And then in apps i import them like this:
var libs = require('shared.libs');
var config = libs.config;
So after this code i can use config which is coming from that shared library.
This part was and is working just fine. But now i need to put additional layer on top of this library (read: provide more unified interface for both apps).
What i tried to do is to add some functions into index.js of shared library and then export the whole object with these functions. But whenever i try to call previously imported (by var libs = require('shared.libs');) object it says that libs is not defined.
What am i doing wrong here?
I generally want to keep other code the same, so i won't need to go over replacing require part everywhere, but at the same time provide additional functionality from shared library which will be available from that imported libs object.
this should definitely work:
module.exports = {
async: require('async'),
config: require('./config'),
utils: require('./lib/utils'),
foo: function () {
return 'bar';
}
};
reference like:
var libs = require('shared.libs');
console.log(libs.async);
console.log(libs.config);
console.log(libs.utils);
console.log(libs.foo);
console.log(libs.foo());
What makes me wonder is one of your comments above, that you get an error libs is not defined. That looks like you should have other unnoticed errors before.. during the the initialization of your shared.libs module..

Resources