I'm building a small node.js/express project and have a function in configure.js that sets configuration options in my express app. For example:
server.js
var express = require('express');
var server = ('./configure');
var app = express();
server.configure(app);
configure.js
exports.configure = function(app) {
app.set('title', 'Server');
};
This doesn't work but I hope it explains what I'm trying to do. I want to make changes to the app instance in server.js. How do I do this?
EDIT:
Okay I think i can get this all working if i understand why this isn't working. Is it to do with timing of the callback? The second console.log() isn't called.
configure.js
var fs = require('fs');
var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');
function configure(app) {
var config = module.exports = {};
fs.readFile('config.txt', function (err, data) {
if (err) throw err;
config.title = decoder.write(data)
console.log(config.title)
});
if(config.title) console.log(config.title);
//app.set('title', config.title)
}
module.exports = function (app) {
configure(app);
};
server.js
var express = require('express');
var cfg = require('./configure');
var fs = require('fs');
var app = express()
cfg(app)
(config.txt is echo 'server' > config.txt)
What you have should actually work.
As for your question about using multiple functions, you can export and call each separately. This can be useful when timing is important (such as if other setup steps need to occur that aren't specified in configure.js):
// configure.js
exports.configure = function (app) {
// ...
};
exports.attachMiddlware = function (app) {
// ...
};
// server.js
var express = require('express');
var server = require('./configure');
var app = express();
server.configure(app);
server.attachMiddlware(app);
You can also define a single entry function as the exported object which calls the functions needed within configure.js. This can possibly keep server.js cleaner by isolating the maintenance within configure.js:
function configure(app) {
// ...
}
function attachMiddleware(app) {
// ...
}
module.exports = function (app) {
configure(app);
attachMiddleware(app)
};
var express = require('express');
var configure = require('./configure');
var app = express();
configure(app);
I would avoid that and just do a json object:
app.js
var cfg = require('./config');
app.set('title', cfg.title);
config.js
var config = module.exports = {};
config.title = 'Server';
Related
I don't know how to structure my code or rather I don't know what happens when an app is built with the below structure. I need to use redis, so is it ok to call it in each module or is this a bad practice?
I have 10 functions that I want to have in separate modules to keep my code readable. I am using express js.
So I have an index.js which looks like this:
const express = require("express");
const app = express();
const port = 3001;
// the separate modules I want to make
let myFirst = require("./first_function");
let mySecond = require("./second_function");
//etc...
app.use("/my_route1",myFirst);
app.use("/my_route2",mySecond);
app.listen(port, () => console.log(`Listnening on port ${port}`));
The first_function.js file looks like this:
const express = require("express");
const router = express.Router();
const redis = require("redis");
const { promisify } = require("util");
const REDISHOST = process.env.REDISHOST;
const REDISPORT = process.env.REDISPORT;
const redisClient = redis.createClient(REDISPORT, REDISHOST);
const getAsync = promisify(redisClient.get).bind(redisClient);
redisClient.on("error", function(err) {
return;
// but since this is an http function should I be calling res.end()?
});
router.all("/", (req,res) =>{
// code for my function
});
module.exports = router;
I will be using redis in quite a few of the modules, so would it just be better to make the index.js file thousands of lines of code or whatever it may come out to be? I don't quite understand what happens when a module is required, if I use 10 modules which all require redis and then require those modules from index.js will I end up with 10 redis clients?
const redis = require('redis');
class Connection {
constructor() {
this.redisClient = redis.createClient({host : "<hostname>", port : "<port>"});
let methods = {};
methods.redisF = false;
if(this.redisconf.cache) {
this.redisClient.on('ready',function() {
methods.redisF = true;
console.log(" Redis cache is up and running ... ");
});
}
this.redisClient.on('error',function() {
methods.redisF = false;
});
}
static makeRedisConnection() {
try {
return this.redisClient;
} catch(error) {
throw "error"
}
}
}
module.exports = Connection;
Whenever you want to query from redis, take the connection in any of the async function from any other module in the below manner, it will help you write less and more structured code.
const redis_conn = Connection.makeRedisConnection();
I am creating a sample project with NodeJs and jsPDF. When I run, it echos ReferenceError: window is not defined. I also used John Gordon answer from here, but again also same problem.
I tried with
var express = require('express');
var jsPDF = require('jspdf');
var app = express();
app.get('/', function(req, res)
{
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
var fs = require('fs');
var jsPDF = require('jspdf');
var jsPDFTable = require('jspdf-autotable');
var doc = new jsPDF();
doc.text("Hello", 10, 10);
var data = doc.output();
fs.writeFileSync('./tmp/storage/pdf/document.pdf', data);
delete global.window;
delete global.navigator;
delete global.btoa;
});
var port = process.env.PORT || 8080;
app.listen(port);
console.log('Server started');
module.exports = app;
All you need to do is to remove your var jsPDF = require('jspdf'); at the top and to have the similar declaration inside your app.get.. (which you already have) function like this,
var express = require('express');
var app = express();
app.get('/', function(req, res)
{
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
var fs = require('fs');
var jsPDF = require('jspdf');
var jsPDFTable = require('jspdf-autotable');
var doc = new jsPDF();
doc.text("Hello", 10, 10);
var data = doc.output();
fs.writeFileSync('./document.pdf', data);
delete global.window;
delete global.navigator;
delete global.btoa;
});
var port = process.env.PORT || 8080;
app.listen(port);
console.log('Server started');
module.exports = app;
Hope this helps!
The specified package jspdf is a client only library and need to be used in a browser environment to work properly.
The description is clear in the package home page:
A library to generate PDFs in client-side JavaScript.
Now, the reason an npm package is available is because bundlers like Webpack and Browserify can load npm packages and convert them into a proper browser compatible script. The require() is not defined in a browser environment and will not work without these bundlers.
So, either choose a library that supports NodeJS like
https://www.npmjs.com/package/pdfkit or shift your PDF related code to browser and work with it.
EDIT:
https://github.com/MrRio/jsPDF/issues/566#issuecomment-382039316
shows that you can use the library in NodeJS env by making the following changes.
In that case, you need to define the global variables before requireing the module.
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
var fs = require('fs');
var jsPDF = require('jspdf');
var jsPDFTable = require('jspdf-autotable');
var app = require('express')();
app.get('/', function(req, res)
{
var doc = new jsPDF();
// ...
}
You can place the script tag either in the head or body tag in the html page, either one is fine. To decide where to place, this answer might be of help
i am using nodejs loopback framework.i want to run a cron job.i created a custom js file for this cron job in server/boot folder.but when manually i run this file(xyz). app is undefined.my code is below
var app = require('../server.js');
console.log(">>>>>>>>>>>>>>in test")
var subscription = app.models.UserNotification;
console.log(">>>>>>>>>>>..in manage")
var datasource=subscription.dataSource;
var query="SELECT DISTINCT userId FROM users_subscription";
datasource.connector.query(sql,function (err, data) {
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>data is>>>>>",data);
})
here is my server.js file
var bodyParser = require('body-parser');
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();
var passport = require('passport');
var bodyParser = require('body-parser').urlencoded({
extended: true
})
app.use(bodyParser)
app.use(loopback.context());
app.use(loopback.token());
var path = require("path");
var url = require('url');
var http = require('http');
var fs = require('fs');
var request = require('request');
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
var baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
var explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
app.use(loopback.static(path.resolve(__dirname, '../client')));
app.use(loopback.static(path.resolve(__dirname, '../admin')));
app.use(loopback.static(path.resolve(__dirname, '../other-dir')));
boot(app, __dirname, function(err) {
if (err) throw err;
if (require.main === module) app.start();
});
Thanks,
It's really impossible to say for sure since you don't include the code that is included with:
var app = require('../server');
(which would be the most important code to include if the require returns undefined) but if app is undefined then it means that the module is loaded but its module.exports is undefined.
Do you export anything from that module?
Are you sure that it is really app that is undefined and not, say, app.models?
Without knowing the code in question those are the most reasonable things to investigate.
Update
If you don't export anything from your server.js (which was my suspection in my answer above, but now you confirmed it with you code and comment) then after this line:
var app = require('../server.js');
you will not be able to use app.models.UserNotification
If you want to use app.models in the code that requires server.js, then you'll have to add:
module.exports.models = SOMETHING;
in your server.js code. You don't seem to have anything called models in server.js, you don't export anything as module.exports.models, so you can't expect app.models to be defined in your code that does:
var app = require('../server.js');
I have a NodeJS + ExpressJS + Socket.IO server and I am trying to divide my different namespaces into different modules.
Essentially I want to require the socket.io library in server.js, but have access to the io variable from my modules like this:
server.js
var app = require('express')();
var jwt = require('jsonwebtoken');
var server = require('http').Server(app);
var fs = require('fs');
var io = require('socket.io')(server);
var bodyParser = require('body-parser');
var _log = require('./logging/loggly.js').Client();
// Global NS
var SK = {
Namespaces:{}
};
var Migrations = require('./sockets/migrations');
var Backups = require('./sockets/backups');
var Cloudmanager = require('./sockets/cloudmanager');
SK.Namespaces[Migrations.NS] = Migrations;
SK.Namespaces[Backups.NS] = Backups;
SK.Namespaces[Cloudmanager.NS] = Cloudmanager;
....
....
migrations.js
var exports = module.exports = {};
///////////////////////////////////////////////
//
// Migrations Namespace
//
///////////////////////////////////////////////
exports.NS = 'migrations';
exports.socket = io.of('/'+exports.NS); // PROBLEM IS 'io' IS UNDEFINED HERE
exports.socket.on('connection', function(socket){
});
I have basically the same code in all 3 of my socket.io namespaces, but I don't have access to the io variable that is used in server.js. Is there a way to have access here? Do I just use a require()? Whats the best way to achieve this functionality?
Thank you
You can export a function from migrations.js that accepts the io value as a parameter:
module.exports = function (io) {
var socket = io.of('/'+exports.NS);
socket.on('connection', function(socket){});
return {
NS: 'migrations',
socket: socket,
};
};
Then simply require and invoke this function in your server.js:
var Migrations = require('./sockets/migrations')(io);
I want to separate my app in to the parts to have something like MVC... Currently I figured out exports works and how to communicate between different files. The one thing i cant understand is that how to use constants in global scope? Currently i have something like this:
// start.js
const ROOT_DIR = __dirname;
const APP_DIR = ROOT_DIR + '/app/';
const MODULES_DIR = '/usr/local/lib/node_modules/';
const APP_PORT = 4935;
var server = require(APP_DIR + 'server.js');
server.start();
// server.js
exports.start = function() {
var express = require(MODULES_DIR + 'express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require(MODULES_DIR + 'socket.io').listen(server),
fs = require('fs'),
path = require('path');
server.listen(APP_PORT);
app.use(express.static(ROOT_DIR + '/assets'));
app.get('/', function (req, res) {
res.sendfile(ROOT_DIR + '/views/index.html');
});
}
Is it possible to automatically assign this constants to server.js or i need to pass them as variables?
I think, you need create file with constants and use him as require file in begin a other module.
File consts.js
exports.CONST_1 = 42,
exports.CONST_2 = 123;
In the module where necessary:
var consts = require('path_to_consts.js');
var my_var = consts.CONST_1 + consts.CONST_2;
So all global variables will be in one place
Object.defineProperty(global, 'MY_CONST', { value : 123 })
P.S. Please, don't do this
Javascript constants won't work globally across files in Node.js. You need to pass them to the function.
// start.js
const ROOT_DIR = __dirname;
const APP_DIR = ROOT_DIR + '/app/';
const MODULES_DIR = '/usr/local/lib/node_modules/';
const APP_PORT = 4935;
var server = require(APP_DIR + 'server.js');
server.start(MODULES_DIR,APP_PORT,ROOT_DIR);
// server.js
exports.start = function(MODULES_DIR,APP_PORT,ROOT_DIR) {
var express = require(MODULES_DIR + 'express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require(MODULES_DIR + 'socket.io').listen(server),
fs = require('fs'),
path = require('path');
server.listen(APP_PORT);
app.use(express.static(ROOT_DIR + '/assets'));
app.get('/', function (req, res) {
res.sendfile(ROOT_DIR + '/views/index.html');
});
}
This is method is same as suggested by #user3040347 but little different.
Here, you need create file with constants and use him as require file in begin of a module in which you want to use.
File consts.js
CONST_1 = 42,
CONST_2 = 123;
module.exports = {};
In the module where necessary:
var consts = require('path_to_consts.js');
var my_var = CONST_1 + CONST_2;
//Here you can access directly