I wanted to write a understandable code in node.js, so I want to put some functions, which are used very often, into other node.js files, and access them from there.
So I get a function, which calls a function from another node.js file and in this other node.js file, also another one is called.
Important to know, if I put all in one file, the code works, so it should be an issue with module export and using functions in another file.
I have one file, getting quotes from a decentralised exchange. Looking like this (quoter_uni_v2.js):
module.exports = function quotes_uni_v2(tokenIn, tokenOut, amountIn, router) {
const quotedAmountOut = router.getAmountsOut(amountIn.toString(), [
tokenIn,
tokenOut,
]);
return quotedAmountOut;
};
And I am importing this function in my second helper file (quotes_5.js) (It is splitted in two files, because in the second one I have to call the function multiple times):
var quotes_uni_v2 = require("./quotes_uni_v2");
module.exports = async function (router1, router2, route, amount_wei) {
console.log(route);
var amount_Out = await quotes_uni_v2.quotes_uni_v2(
route[1],
route[2],
amount_wei,
router1
);
...
return (
Math.round(ethers.utils.formatEther(amount_Out[1].toString()) * 100) / 100
);
};
After that I try to call the function in my main.js:
const quotes_uni_v2 = require("./quotes_uni_v2");
const quotes_5 = require("./quotes_5");
async function calc(route) {
amountOut = await new quotes_5(
quickswap_router,
sushiswap_router,
route,
amount_wei
);
return amountOut;
};
But calling the quotes function does not work... The error is:
TypeError: quotes_5 is not a constructor...
Can someone help me?
Thanks!
I need to know the difference between these two approaches developer uses in nodeJS development to include a module.
First approach (passing module in app by importing it once and using it by passing as parameter or binding it to app as property )
Server.js (app entry point)
let app = require('express').express();
let Router = require("./routes");
let SomeModule = require("./some-module");
.....
.....
Router.mountAPI("/api", app, SomeModule);
.....
....
routes.js (Passing pre imported module to controllers in different files )
let Ctrl1fun = require("./ctrl1");
let Ctrl2fun = require("./ctrl2");
exports.mountAPI = function(mount, app, SomeModuleToUseInController) {
app.use(mount + '/endpoint1', Ctrl1fun(SomeModuleToUseInController));
app.use(mount + '/endpoint2', Ctrl2fun(SomeModuleToUseInController));
};
ctrl1.js (Controller for end point 1 )
module.exports = function(SomeModule) {
....
....
//using SomeModule
}
// This file may contain some other controller function for simplicity i took only one
ctrl2.js (Controller for end point 2 )
module.exports = function(SomeModule) {
....
....
//using SomeModule
}
// This file may contain some other controller function for simplicity i took only one
2.Second approach (Each controller importing the module)
Server.js (app entry point)
let app = require('express').express();
let Router = require("./routes");
.....
.....
Router.mountAPI("/api", app);
.....
....
routes.js (module imported in controllers )
let Ctrl1fun = require("./ctrl1");
let Ctrl2fun = require("./ctrl2");
exports.mountAPI = function(mount, app) {
app.use(mount + '/endpoint1', Ctrl1fun());
app.use(mount + '/endpoint2', Ctrl2fun());
};
ctrl1.js (Controller for end point 1 )
let SomeModule = require("./some-module");
module.exports = function() {
....
....
//using SomeModule
}
// This file may contain some other controller function for simplicity i took only one
ctrl2.js (Controller for end point 2 )
let SomeModule = require("./some-module");
module.exports = function() {
....
....
//using SomeModule
}
// This file may contain some other controller function for simplicity i took only one
Witch one is better if we consider
App size (API and controllers function in different controller files)
Application performance
Best practices
The difference in terms of size and performance will be negligible.
The second approach is simpler and I would consider it as the best one unless you need to inject different modules into the same controller type, e.g. a generic CRUD controller parameterized by model type
i built an app on 1 page, and now i want to oragenize all of its functions and objects in seperate files and directories, and import them to the app.js file. but im having some problems with global objects, the the imported functions dosent recognize them.
example:
//app.js
const req_obj = require("./objectFile.js")
const tool = {
number:4
}
req_obj.obj.addFive() // this will print "cant read number of undefined"
//objectFile.js
const req_func = require("./function.js")
exports.obj = {
addFive:req_func.addFive
}
//function.js
exports.addFive = function(){
return tool.number + 5
}
i know that it might be that im doing all wrong, and this is not how you orgenize an app and call its function. i whould be really glad if some1 will explaine my how to orgenize an app, and call its functions the right way, if what i did is wrong.
The only possibility you have to get access to variables from multiple files is to have them in a separate file and export them like this:
// objects.js
const tool = {
number:4
}
exports.tool = tool
Which then makes your app.js look like:
//app.js
const req_obj = require("./objectFile.js")
const tool = require("./objects.js").tool
// this will read 9
console.log(req_obj.obj.addFive())
And your function.js then becomes:
const tool = require("./objects.js").tool
exports.addFive = function(){
return tool.number + 5
}
Hope it helps.
I'm having hard time figuring out why my module isnt sigleton, as it should be by default, and why its variables suddenly resetting. Any attempts to make a variable a member of the module.exports object got the same result with unpredictable behavior.
This is completely baffling to me and I would be grateful for any help.
//target module, ./api/models/person/index.js:
"use strict";
module.exports = {};
var own_counter = 0;
module.exports.setup = function () {
console.log('setup, pre own_counter = ' + own_counter);
++own_counter;
console.log('setup, post own_counter = ' + own_counter);
}
//first use, ./api/hooks/sequelizeConnecionsInit/index.js:
...
initialize: function(done){
var person_orm = require('../../models/person');
person_orm.setup();
person_orm.setup();
return done();
},
...
//second use, ./node_modules/sails-userhooks-ws/index.js:
...
var person_orm = require('../../api/models/person');
person_orm.setup();
...
//(its wrong to write code to node_modules, but I havent figured out yet how to use it with my code without module code change)
//Output:
...
setup, pre own_counter = 0
setup, post own_counter = 1
setup, pre own_counter = 1
setup, post own_counter = 2
...
setup, pre own_counter = 0 //Why resetted???
setup, post own_counter = 1
...
The reason was here:
http://justbuildsomething.com/node-js-best-practices/#2
In the first and second using too I called require inside the functions, so when I moved it to head (global scope?), my problem resolved.
I know some inner functionality inside Webpack. Something about dependencies, template, and module building. However, there is little comment inside its source and no full document site for now. So, i can't chain them all to deal with my problem.
With my current requirement, i need to render specific module with custom source template (similar to this MultiModule in webpack).
Note: To be clear, the generated module's dependency array is not static. For example, one time it may be ['./a', './b', './c'], another time it may be ['./b', './c','./d']. That is up to some dynamic config before build.
For more detail example, i need a module call main.js. In build time, it need to be dynamically generated with target dependencies like(for being not sure which modules would be dependencies):
// main.js
var a = require('./a')
var b = require('./b')
var c = require('./c')
var d = require('./d')
...
In fact, if i only need to dynamically require them all, i can just construct an entry point dynamically.
// webpack.config.js
{
entry: {
main: [
'./a',
'./b',
'./c',
...
]
},
}
and it(webpack) will generate a module may like this:
__webpack_require__(1);
__webpack_require__(2);
__webpack_require__(3);
return __webpack_require__(4);
But i need to do something more:
var a = __webpack_require__(1);
var b = __webpack_require__(2);
var c = __webpack_require__(3);
var d = __webpack_require__(4);
...
// do something with a,b,c,d... under my custom need
...
return somthing or nothing;
As you guys who know about webpack, it's very very complicated and hard to understand and track its plugin(event) hierarchy.
Need some expertise! :)
I'm sorry foy my unclear question before.
However, there is some kind of weird atmosphere. I set up a bounty for attention and guidance. Someone's free-minded answer drove me to make comment with impoliteness somehow. And then some peacemaker shows up with comments unrelated to the question or answer. That sucks.
Focusing on that thing just makes things worse and nothing helped. Not letting it go just means someone has petty mind.
Either lacking attention and lacking expert or not, I have to fight it myself. Fortunately, digging into webpack makes some progress.
Prerequisite
The day before popular webpack, there are fashions like grunt and gulp to construct a custom build flow (with their plugins). They can achieve most of custom requirement, especially generating a custom module(which webpack doesn't have obvious and direct way to deal with).
when you come to do something like automatic collecting custom dependencies, then generating a custom module is the next essential step. It can be commonly seen in product line/family design.
Solutions
#1
This is the simplest and direct way but lack of flexibility.
The source method of MultiModule is to generate the entry module with multi-dependencies. Just overriding it will hit the target.
// hack.js
const MultiModule = require('webpack/lib/MultiModule')
MultiModule.prototype.source = function(dependencyTemplates, outputOptions) {
var str = ['"hello world";\n'];
this.dependencies.forEach(function (dep, idx) {
if (dep.module) {
if (idx === this.dependencies.length - 1)
str.push("module.exports = ");
str.push("__webpack_require__(");
if (outputOptions.pathinfo)
str.push("/*! " + dep.request + " */");
str.push("" + JSON.stringify(dep.module.id));
str.push(")");
} else {
str.push("(function webpackMissingModule() { throw new Error(");
str.push(JSON.stringify("Cannot find module \"" + dep.request + "\""));
str.push("); }())");
}
str.push(";\n");
}, this);
return new RawSource(str.join(""));
}
At the fifth line, i add a string statement "hello world;"\n, nothing else changed.
module.exports = {
entry: {
main: ["./a", "./b"],
}
// something else
}
the output main.js may look like:
//...
/* 0 */
/*!******************!*\
!*** multi main ***!
\******************/
/***/ function(module, exports, __webpack_require__) {
"hello world";
__webpack_require__(/*! ./a */1);
module.exports = __webpack_require__(/*! ./b */2);
/***/ }
//...
Now we can do what we want with the source method, with the compatibility in mind.
#2
This way is much more flexible but also complex.
It requires at lease 5 files(sources are too long, I made them into snippets):
CustomMultiModule.js:
// CustomMultiModule.js
const MultiModule = require('webpack/lib/MultiModule')
const RawSource = require('webpack/lib/RawSource')
class CustomMultiModule extends MultiModule {
constructor(...args) {
super(...args)
}
source(dependencyTemplates, outputOptions) {
var str = ['"hello world";'];
this.dependencies.forEach(function(dep, idx) {
if (dep.module) {
if (idx === this.dependencies.length - 1)
str.push("module.exports = ");
str.push("__webpack_require__(");
if (outputOptions.pathinfo)
str.push("/*! " + dep.request + " */");
str.push("" + JSON.stringify(dep.module.id));
str.push(")");
} else {
str.push("(function webpackMissingModule() { throw new Error(");
str.push(JSON.stringify("Cannot find module \"" + dep.request + "\""));
str.push("); }())");
}
str.push(";\n");
}, this);
return new RawSource(str.join(""));
}
}
module.exports = CustomMultiModule
CustomMultiModuleFactory.js:
// CustomMultiModuleFactory.js
const MultiModuleFactory = require('webpack/lib/MultiModuleFactory')
const CustomMultiModule = require('./CustomMultiModule')
class CustomMultiModuleFactory extends MultiModuleFactory {
constructor() {
super()
}
create(context, dependency, callback) {
callback(null, new CustomMultiModule(context, dependency.dependencies, dependency.name));
};
}
module.exports = CustomMultiModuleFactory
CustomMultiEntryPlugin.js:
// CustomMultiEntryPlugin.js
const MultiEntryPlugin = require('webpack/lib/MultiEntryPlugin')
const MultiEntryDependency = require('webpack/lib/dependencies/MultiEntryDependency')
const CustomMultiModuleFactory = require('./CustomMultiModuleFactory')
class CustomMultiEntryPlugin extends MultiEntryPlugin {
constructor(context, entries, name) {
super(context, entries, name)
}
apply(compiler) {
compiler.plugin('after-plugins', function(compiler) {
compiler.plugin("compilation", function(compilation, params) {
var multiModuleFactory = new CustomMultiModuleFactory();
compilation.dependencyFactories.set(MultiEntryDependency, multiModuleFactory);
})
})
}
}
module.exports = CustomMultiEntryPlugin
CustomEntryOptionPlugin.js:
// CustomEntryOptionPlugin.js
const CustomMultiEntryPlugin = require('./CustomMultiEntryPlugin')
class CustomEntryOptionPlugin {
constructor() {}
apply(compiler) {
compiler.plugin("entry-option", function(context, entry) {
if (typeof entry === "object") {
Object.keys(entry).forEach(function(name) {
if (Array.isArray(entry[name])) {
compiler.apply(new CustomMultiEntryPlugin(context, entry[name], name));
}
});
}
});
}
}
module.exports = CustomEntryOptionPlugin
webpack.config.js:
// webpack.config.js
const CustomEntryOptionPlugin = require('./CustomEntryOptionPlugin')
module.exports = {
entry: {
main: ["./a", "/b"] // this dependencies array may be generated
...
},
output: {
path: path.join(__dirname, "js"),
pathinfo: true,
filename: "[name].[chunkhash].js",
chunkFilename: "[chunkhash].js"
}
plugins: [
new CustomEntryOptionPlugin(),
...
]
...
};
With the code above, we can achieve the same as #1. And we can gain more control over the target entry or other requirements, if we want.
Often in webpack you're only requiring one file, and maybe different libs that the files depend on. If you require main, then webpack is going to resolve the dependencies based on the CommonJS syntax which you can read about here. Does removing the extra requirements in your webpack.config.js file solve this? e.g. having only the following as the config:
// webpack.config.js
{
entry: [ "./main" ],
...
}
It sounds like you don't really understand how webpack works-- the idea of it is to emulate how Node's CommonJS syntax allows your javascript to be modular and placed in separate files, while also being performant and not requiring tons of AJAX requests by your browser. If you want to read more about Webpack's config file, check out this page.
As a side note, returning at the end of the module does absolutely nothing. If you want to export, you can use module.exports, but having a line like return true or something at the end of your main.js file doesn't get caught anywhere meaningful.