modify nodejs require() to search for .min.js - node.js

O/S is ubuntu 16, node version is 4.2.6.
I have source / development code and run / distribution code, the source.js files are minified and mangled to create equivalent source.min.js files, and I would like for node js require to automatically search for .min.js files as well as .js files.
But as I have a lot of files, I would prefer not to have to go through every require in every file and instead modify the built-in require() function.
This is a very simple implementation of a stand alone function, but how can I modify the built-in function to behave the same way ?
function require(file){
try{return require(file)}
catch(e){return require(file+='.min.js')}
}

You can achieve this by modifying prototype function require of Module class and apply it globally
Here is how you can do it :
var pathModule = require('path');
var assert = require('assert').ok;
module.constructor.prototype.require = function (path) {
var self = this;
assert(typeof path === 'string', 'path must be a string');
assert(path, 'missing path');
try {
return self.constructor._load(path, self);
} catch (err) {
// if module not found, we have nothing to do, simply throw it back.
if (err.code === 'MODULE_NOT_FOUND') {
throw err;
}
// resolve the path to get absolute path
path = pathModule.resolve(__dirname, path+".min.js")
// Write to log or whatever
console.log('Error in file: ' + path);
}
}

Related

change requireJS from adding the .js file extension automatically on intern.js

Currently I am working in custom html reporter for intern.js. The Templating engine that i am using is marko.js.
marko.js have extension file with ".marko" for me to input my html syntax
The file is generated correctly in normal node.js (common.js)
The issue occurred when i integrate the same code to intern.js. The requirejs(AMD) that use by internjs is adding the .js file extension automatically to my marko extension when i do
var template = require('./hello-world.marko');
which make the file become hello-world.marko.js and this caused the code broke in markojs
the custom html reporter code is below
define(function (require) {
// require('intern/dojo/node!marko/node-require').install();
var fs = require('intern/dojo/node!fs');
var template = require('./hello-world.marko');
console.log(template);
function JsonReporter(config) {
config = config || {};
this.output = config.output;
}
JsonReporter.prototype = {
runEnd(executor) {
// console.log("toJson: " + JSON.stringify(executor.suites))
data = JSON.stringify(executor.suites);
template.renderToString(data,
function (err, output) {
console.log(output);
fs.writeFile('result.html', output, function (err) {
if (err) return console.log(err);
console.log('Save done');
});
});
},
}
return JsonReporter;
})
The require function isn't really meant for loading arbitrary text resources in either Node's loader or an AMD loader. In Node, whether you're running Intern or not, you can use fs.readFile or fs.readFileSync. In Intern's Dojo-based AMD environment you can also use the dojo/text loader plugin, like this:
var template = require('dojo/text!./hello-world.marko');

Path resolution issues with NPM modules vs apps

I am writing a module that will be used as a dependency for Node.js apps. In some cases, it will be a dependency of a dependency, which means the path resolution will change, and currently I am having a problem with that. Namely, when my module is a dependency of a dependency, my module will still look to the app root, not the root of the dependency.
I think the shortest way to ask a question on how to solve this is to find out the best way to determine if the module is a dependency or not.
So the way to do that would be to get the __dirname of the file in the index of my module and then navigate up one directory to see if that directory is named node_modules.
Is there a better way to do this? Is there a better way to determine if the code being invoked is being invoked from a dependency of the app or from the app itself?
Visually speaking, it looks like this
--app
---/node_modules
-----/A
-----/B
my module is called A
A could be used by app, or it could be used by B
if it's used by app, I can use the app-root-path module to quickly determine the root. But if my module is used by B, how will I know that? It will matter for resolving paths.
Here is the entiriety of the code in my module:
var appRoot = require('app-root-path');
var path = require('path');
var configs = {};
function checkIfDependency(){
var temp = path.resolve(path.normalize(__dirname + '/../'));
return path.basename(temp) === 'node_modules';
}
module.exports = function (identifier, pathToProvider) {
if (String(identifier).indexOf('*') < 0) {
throw new Error('did not pass in an identifier to univ-config');
}
if (configs[identifier]) {
return configs[identifier];
}
else {
if (pathToProvider) {
try {
var configPath;
if (path.isAbsolute(pathToProvider)) { //consumer of this lib has been so kind as to provide an absolute path, the risk is now yours
configPath = path.normalize(pathToProvider);
}
else if(checkIfDependency()){ //univ-config is being invoked from a dependency
configPath = path.normalize(??? + '/' + pathToProvider);
}
else{ //univ-config is being invoked from an app
configPath = path.normalize(appRoot + '/' + pathToProvider);
}
var f = require(configPath);
return configs[identifier] = f();
}
catch (err) {
throw new Error('univ-config could not resolve the path to your config provider module - given as:' + pathToProvider);
}
}
else {
throw new Error('no config matched the identifier but no path to config provider was passed to univ-config');
}
}
};

Is there an alternative to require() in Node.JS? A "soft require" which tries to find a file but doesn't error if it isn't there

I'm loading a config.json file using require('./config.json') but I don't want to require a config file if they want to pass command line arguments instead, or just use the defaults. Is there any way to try to load a JSON file this way but not spit out an error if it can't be found?
For general modules, you can check for existence before trying to load. In the following path is whatever path you want to load and process() is a function performing whatever processing you'd like on your module:
var fs = require("fs");
fs.exists(path, function (exists) {
if (exists) {
var foo = require(path);
process(foo);
}
else {
// Whatever needs to be done if it does not exist.
}
});
And remember that path above must be an actual path, and not a module name to be later resolved by Node as a path.
For a JSON file specifically, with path and process having the same meanings as above:
fs.readFile(path, function (err, data) {
if (err) {
// Whatever you must do if the file cannot be read.
return;
}
var parsed = JSON.parse(data);
process(parsed);
});
You can also use try... catch but keep in mind that v8 won't optimize functions that have try... catch in them. With path and process meaning the same as above:
try {
var foo = require(path);
process(foo);
}
catch (e) {
if (e.code !== "MODULE_NOT_FOUND")
throw e; // Other problem, rethrow.
// Do what you need if the module does not exist.
}

How to check in node if module exists and if exists to load?

I need to check if file/(custom)module js exists under some path. I tried like
var m = require('/home/test_node_project/per');
but it throws error when there is no per.js in path.
I thought to check with
fs if file exists but I don't want to add '.js' as suffix if is possible to check without that.
How to check in node if module exists and if exists to load ?
Require is a synchronous operation so you can just wrap it in a try/catch.
try {
var m = require('/home/test_node_project/per');
// do stuff
} catch (ex) {
handleErr(ex);
}
You can just try to load it and then catch the exception it generates if it fails to load:
try {
var foo = require("foo");
}
catch (e) {
if (e instanceof Error && e.code === "MODULE_NOT_FOUND")
console.log("Can't load foo!");
else
throw e;
}
You should examine the exception you get just in case it is not merely a loading problem but something else going on. Avoid false positives and all that.
It is possible to check if the module is present, without actually loading it:
function moduleIsAvailable (path) {
try {
require.resolve(path);
return true;
} catch (e) {
return false;
}
}
Documentation:
require.resolve(request[, options])
Use the internal require() machinery to look up the location of a module, but rather than loading the module, just return the resolved filename.
Note: Runtime checks like this will work for Node apps, but they won't work for bundlers like browserify, WebPack, and React Native.
You can just check is a folder exists by using methods:
var fs = require('fs');
if (fs.existsSync(path)) {
// Do something
}
// Or
fs.exists(path, function(exists) {
if (exists) {
// Do something
}
});

Node.js customize require function globally

I am trying to modify require like this
require = function (path) {
try {
return module.require(path);
} catch (err) {
console.log(path)
}
}
However, scope of this modification is only in the current module. I want to modify it globally, so every module that is required by this module will also get the same copy of require function.
Basically, I want to catch SyntaxError to know which file has problem. I can't seem to find any other alternative. If I put module.require in try/catch block, I'll be able to get the file name which caused SyntaxError.
I managed to solve it by modifying prototype function require of Module class. I put this in the main script and its available to all the required modules.
var pathModule = require('path');
var assert = require('assert').ok;
module.constructor.prototype.require = function (path) {
var self = this;
assert(typeof path === 'string', 'path must be a string');
assert(path, 'missing path');
try {
return self.constructor._load(path, self);
} catch (err) {
// if module not found, we have nothing to do, simply throw it back.
if (err.code === 'MODULE_NOT_FOUND') {
throw err;
}
// resolve the path to get absolute path
path = pathModule.resolve(__dirname, path)
// Write to log or whatever
console.log('Error in file: ' + path);
}
}
Why don't you use a try-catch block inside your code and once an error occurs to check the stack trace. Check out these links
How to print a stack trace in Node.js?
http://machadogj.com/2013/4/error-handling-in-nodejs.html

Resources