I'm new to JavaScript/Nodejs. How can I share my configuration across the Nodejs application. For example: I have a config/config.coffee
path = require("path")
module.exports = {
development:
db: 'mongodb://localhost/hello'
root: rootPath = path.normalize(__dirname + '/..')
}
I included config.coffee in my app.coffee.
express = require("express")
# Load configurations
env = process.env.NODE_ENV || 'development'
config = require("./config/config")[env]
require('./config/boot')
app = express()
Now I want to include config variable into my config/boot.coffee. How can I do it? I don't want to re-include config/config.coffee into config/boot.coffee. Here is the my config/boot.coffee file:
env = process.env.NODE_ENV || 'development'
config = require("./config")[env]
fs = require("fs")
mongo = require("mongoose")
# Bootstrap db connections
mongo.connect config.db
# Bootstrap models
models_path = config.root+"/app/models"
fs.readdirSync(models_path).forEach( (file)->
require(models_path + '/' + file) if ~file.indexOf('.coffee')
)
# Bootstrap services
services_path = config.root+"/app/services"
fs.readdirSync(services_path).forEach( (file)->
require(models_path + '/' + file) if ~file.indexOf('_service.coffee')
)
Sorry for bad English :(
You might want to check out nconf, which helps you keep a kind of "waterfall" approach to application configuration, which allows you to mix your configuration from different sources very transparently.
You can see nconf in action in this project I wrote, unbox, which is basically boilerplate I use for applications I write on Node. You can check out how configuration is loaded here.
You could use something like grunt-pemcrypt for increased security by checking in the secure, encrypted file, and saving the encryption key somewhere safe.
12factor also has a nice approach to application configuration you might want to look into.
I believe NodeJS caches your require's, so calling require('config') again won't cause any performance degradation.
http://nodejs.org/api/globals.html#globals_require
Related
I have two angular projects and I want to serve them on the same domain like for example if I do mywebsite.com/app1 get the first project and when I do mywebsite.com/app2 get the second project.
If you need them to run on the same node server then just create controller routes for each to separate them. If you mean that you both need them to run on the same physical server then you can look into sub domains and have app1.mywebsite.com point to one running node server and app2.mywebsite.com point to another. This would allow them to be split between 2 node processes.
Simply make 2 folders inside dist for each app and serve the static files using express.static
var express = require('express');
var path = require('path');
var app = express();
app.use('/app1', express.static(path.normalize(__dirname + './../dist/app1')));
app.use('/app2', express.static(path.normalize(__dirname + './../dist/app2')));
create two folder on your node app
app1
app2
put the result of ng build of both project in those folders by editing your angular.json file and specify the outDirand the same for the scond app 'app2' :
"outDir": "/path/to/your/node/app/app2"
"outDir": "/path/to/your/node/app/app1"
then in your node app just tell the app which folder to serve from on the specific route :
app.use('/app1', express.static('app1'));
app.use('/app2', express.static('app2'));
app.use('/', express.static('index.html'));
I have this code now, it is serving the correct app but in Angular it isn't finding the correct js files it's looking in the root directory like localhost:8080/main.js instead it must look at localhost:8080/app1/main.js
const express = require('express');
const app = express();
const path = require('path');
app.use('/app1', express.static(path.normalize(__dirname + '/app/app1')));
app.use('/app2', express.static(path.normalize(__dirname + '/app/app2')));
app.listen(8080, () => {
console.log('Server is litening on port 8080');
});
How do I use socket.io with browserify?
When socket.io is installed in a node app, it creates this url path for ths socket.io script:
/socket.io/socket.io.js
But what would be the real path of that file (relative to the node_modules dir) which needs to be passed to browserify?
Is it e.g.
socket.io-client/socket.io.js
or maybe
socket.io/lib/client.js
In the documentation of socket.io-client it says "Socket.IO is compatible with browserify." But they don't say how.
If you struggled to get it working with browserify as a window global use this code for the integration:
var io = require('socket.io-client');
window.io = io;
Here's a minimal client:
// client.js
var socket = require('socket.io-client')();
socket.on('message', ...);
Which you can Browserify:
browserify client.js > bundle.js
The path will be exactly the same since it's the server who serve the socket.io client library (and I guess you're not browserifying the server, are you?).
But I use a more convenient solution: check this out.
io = require 'socket.io-client'
class Network
constructor: (game, refresh_infos) ->
#sock = io()
#...
pending: (name, cb) ->
#name = name
#sock.emit 'pending', name: name
#sock.on 'new_game', (data) => cb data
Abrakadabra!
Import client and then assign it to variable with:
var client = require('socket.io/lib/client');
You can then call client.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
How do you structure your project for full stack development, such that the js in /webapp could be processed by a gulp/grunt/webpack tools - in exploded war.
I know I can have maven/gradle add a step to perform some "npm thing", but that's a full build. I'll have that too, but I need the instant reload feature for development.
I want to be able to save a js file, have a watcher pick it up, process it and throw it back into my exploded war, in such a way that it a) doesn't pollute my /src/main/webapp/ b) I want it to coexist with my java webapp on the same root context (have my jsp's and eat it too).
One thing I considered is having my processes js outputed to some /src/main/webapp/do_not_checkin_folder and doing an equivalent of .gitignore on that directory. Followed up by, the full gradle/maven build that would rewrite paths in index.html removing any mention of do_not_checkin_folder and shortening the path to start from /src/main/webapp. Call it production mode.
Can someone suggest a different approach. What worked for you on your project?
I have a Node server running Express that proxies most requests to my Java web server, except for the js requests, which it uses webpack hot middleware to serve.
Webpack is configured to use the contents src/main/js with webpack-hot-middleware to generate the single js page.
So in development, you navigate the to Node Express server. In production, the static js file is served by the Java web server.
Here's my server.js for Node:
const PROXY_TARGET = 'http://localhost:9501';
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const config = require('./webpack.config-hot-middleware');
const express = require('express');
const proxy = require( 'http-proxy' );
const proxyServer = proxy.createProxyServer( );
proxyServer.on('error', function(err, req, res) {
console.log('Proxy error: ' + err);
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Proxy request to ' + PROXY_TARGET + ' failed. Please make sure your Java server is running!');
});
const app = new require('express')();
const port = 3000;
const compiler = webpack(config);
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }));
app.use(webpackHotMiddleware(compiler));
app.use('/', function(req, res) {
proxyServer.web(req, res, {
target: PROXY_TARGET
});
});
app.listen(port, function(error) {
if (error) {
console.error(error);
} else {
console.info('==> Listening on port %s.);
}
});
What would be the best way to store DB config (username, password) in an open source app that runs on node.js / Express? Two specific questions:
Shall I put it into a separate config.js file in /lib folder, for example, and never include it into the master repository that is publicly available on GitHub?
To inlcude the config, is it as simple as require('./config.js') from the file that needs it or is there a better way of doing it?
PS sorry if the questions seem a bit simple or not so well formulated, but I'm just starting :)
Here's how I do it:
Create a config.js which contains objects representing your configs:
var config = {
development: {
//url to be used in link generation
url: 'http://my.site.com',
//mongodb connection settings
database: {
host: '127.0.0.1',
port: '27017',
db: 'site_dev'
},
//server details
server: {
host: '127.0.0.1',
port: '3422'
}
},
production: {
//url to be used in link generation
url: 'http://my.site.com',
//mongodb connection settings
database: {
host: '127.0.0.1',
port: '27017',
db: 'site'
},
//server details
server: {
host: '127.0.0.1',
port: '3421'
}
}
};
module.exports = config;
Then in my index.js (or wherever really),
var env = process.env.NODE_ENV || 'development';
var config = require('./config')[env];
Then process with that object, e.g.
var server = express();
server.listen(config.server.port);
...
For running toy apps where I need to hide db credentials, I use the dotenv module.
Place your sensitive info in a .env file (which is .gitignored), place require('dotenv').config(); in your app; dotenv creates entries in process.env that you can refer to.
.env file:
DATABASE_PASSWORD=mypw
DATABASE_NAME=some_db
To refer to the values:
process.env.DATABASE_PASSWORD
Not sure whether this is the best practice, but personally I have a config.json file where I store my db connection information. Then I do the following:
// options.js
var fs = require('fs'),
configPath = './config.json';
var parsed = JSON.parse(fs.readFileSync(configPath, 'UTF-8'));
exports.storageConfig= parsed;
Then from a different file I do the following:
var options = require('./options');
var loginData = {
host: options.storageConfig.HOST,
user: options.storageConfig.user,
password: options.storageConfig.password
};
I do put in args. just like the port of so many node.js example.
you most likely forever, pm2, nodemon to run your app. so this variable is not check in as part of your source code. and they are globally available too.
process.env.PORT
process.env.DATABASE_USER
process.env.DATABASE_PASSWORD
PORT=3000 DATABASE_HOST=localhost DATABASE_USER=admin DATABASE_PASSWORD=mypassword node app.js
export PORT=3000
export DATABASE_HOST=localhost
export DATABASE_PORT=27017
export DATABASE_USER=admin
export DATABASE_PASSWORD=mypassword
node app.js
var server = app.listen(process.env.PORT, function() {
});
var mongoClient = new MongoClient(new Server(process.env.DATABASE_HOST, process.env.DATABASE_PORT));
To inlcude the config, is it as simple as require('./config.js') from the file that needs it or is there a better way of doing it?
This is the right way to store config files.
The best approach would be to write your entire application like an ordinary node.js module, and write a small start-up file that calls it. This idea also allow you to use different database drivers using dependency injection.
Good, but not perfect solution is the environment. It is shared among all application, so if you have certain data you want to be available to all of them, this is the best bet. But if you have a config for one particular app, not much so.
PS: And please, don't use JSON for this. It's the worst idea possible. :)
I found this a nice way to handle my config, considering different environments:
config.coffee
exports.setEnvironment = (env) ->
switch env
when "development"
exports.DEBUG_LOG = true
exports.DB_PORT = '27017'
# ...
when "testing"
exports.DEBUG_ERROR = true
exports.DEBUG_CLIENT = true
# ...
when "production"
exports.DEBUG_LOG = false
# ...
else console.log "environment #{env} not found"
server.coffee:
config = require('./config')
config.setEnvironment env
Using environment variables
You can use export to set environment variables in OSX and Linux. The following is an example of setting a value in the SESSION_SECRET key.
export SESSION_SECRET="keyboard cat"
In Windows, you can use set.
set SESSION_SECRET="keyboard cat"
You can also set environment variables each time you run them.
SESSION_SECRET="keyboard cat" node secret-env.js
Use process.env of node.js to access environmental variables within code.
var express = require('express')
var session = require('express-session')
var app = express()
app.use(session({secret: process.env.SESSION_SECRET}))
Request a argument from the command-line
The best way to protect confidential information is not to store it in a setup file.
If the command-line requests configuration information as an argument using the noopt package, the secret information does not need to exist as a file.
The following is an example of requesting a session key as an argument using the noopt package.
var nopt = require("nopt")
var longOpts = {
"sessionSecret": String,
}
var shortOpts = {
"s": ["--sessionSecret"],
}
var parsed = nopt(longOpts, shortOpts, process.argv, 2)
console.log("session secret is:", parsed.sessionSecret)
node secret-arg.js --sessionSecret "keyboard cat"
node secret-arg.js -s "keyboard cat"
Advantages : It is safer to expose confidential information than to hardcoding or having it as a configuration file.
Disadvantages : There is a hassle of increasing the amount of information to be entered each time the app is launched.
If you try to create and solve a script, the problem that the password still exists in the script remains.
Taking the simple example from Union, I am wondering where I can put configuration code that usually goes in app.configure, like passport.js:
app.configure(function() {
// Initialize Passport! Also use passport.session() middleware, to support
// persistent login sessions (recommended).
app.use(passport.initialize());
app.use(passport.session());
});
Any ideas? server and router don't accept use().
Union appears to use the before collection for this:
var server = union.createServer({
before: [
connect.session({ secret: 'keyboard cat' }), // for `passport.session()`
passport.initialize(),
passport.session(),
// etc.
]
});
From the "API" documentation:
#option before {Array}
The `before` value is an array of middlewares, which are used to route and serve incoming
requests. For instance, in the example, `favicon` is a middleware which handles requests
for `/favicon.ico`.
Union supports connect middlewares via the before property, as previously mentioned by others. However, union does not handle application configuration; flatiron does. The api, however, is significantly different from express.
For example, configuring an application may look something like this:
var path = require('path'),
flatiron = require('flatiron'),
app = flatiron.app,
plugins = flatiron.plugins,
connect = require('connect'), // most connect middlewares work with flatiron ootb
passport = require('passport');
// Use flatiron's http plugin (not the same as a middleware!)
app.use(plugins.http);
// configuration consists of key/value pairs, not of function blocks associated with
// certain "environments".
// Here's *a* way you can handle environment-based configs; there are others!
app.config.file(path.resolve(
__dirname,
'config',
(process.env.NODE_ENV || 'config') + '.json'
));
// Use our config to set the secret
app.http.before.push(connect.session({
secret: app.config.get('secret') || 'keyboard cat' //default
}))
app.http.before.push(passport.initialize());
app.http.before.push(passport.session());
I haven't tried running this example (I'm sure there are more details here) but hopefully this gives you an idea.
I just built a wrapper to integrate Passport.js with Flatiron.js.
https://npmjs.org/package/flatiron-passport
https://github.com/travist/flatiron-passport
Please read the README.md on how to use it and apply it to your application.
I have tested it on LocalStrategy, but it should work for other strategies.
Please let me know otherwise.