Meteor: How to separate local environment from production? - node.js

I have two pieces of code: one that must only be run in a local environment and the other in production. What is the best way to do that in Meteor?

You can check do
(server side)
var isDevelopment = function() {
var i = WebApp.clientProgram.manifest.length;
while(i--) {
if('sourceMap' in WebApp.clientProgram.manifest[i]) return true;
}
return false;
}
if(isDevelopment()) {
console.log("Dev mode");
}else{
console.log("Production");
}
The idea is to check for JS Source Maps, which are only available in dev mode. This should work out of the box with your meteor app without any special configuration.

I prefer to set an environment variable which the server can read. For example:
$ METEOR_ENV="production" meteor
Then on the server:
if (process.env.METEOR_ENV === 'production') {
// production code here
} else {
// dev code here
}
If you have only two states, you could assume !production = dev.

Use this package and you will haveMeteor.isdevelopment only in development. There is other packages out there too that do the same thing but differently. this is the simplest

Related

Where do i need to set karate.config.dir to run my tests in multiple environments

My current config file looks something like this:
function() {
var env = karate.env;
karate.log('karate.env system property was:', env);
karate.configure('ssl', true);
if (!env) {
env = 'dev';
}
var config = {
env: env,
internalGateway: 'https://gateway.com.au',
externalGateway: 'https://gateway.com.au',
GatewayManagerURL: 'https://manager.com.au'
}
if (env == 'dev') {
}
else if (env == 'e2e') {
}
return config;
}
This is the only file I have for environments. I am unsure as to how can I run my tests in multiple environments.
Do I need to create a new karate.config.<env>.js file (as per the docs) to run my tests in a new environment?
You need only this one file. Now the config JSON returned has some default values set. What you can do now is have different values for e2e, for example:
else if (env == 'e2e') {
config.internalGateway = 'https://gateway-e2e.com.au';
}
And when you run your tests, you switch environments on the command-line. This is just setting a Java System Property. There are many other ways to do this:
mvn test -DargLine="-Dkarate.env=e2e"
All this is explained here: https://github.com/intuit/karate#switching-the-environment

process.env.NODE_ENV not matching 'development' no matter what

Just migrated on the latest Express, and stuck in something completely simple.
So, how is it possible, that this distilled example:
var env = process.env.NODE_ENV || 'development';
console.log(env);
if ('development' == env) {
console.log('im here');
}
else {
console.log('nah');
console.log(env);
}
with this server file runned as SET NODE_ENV=development & node server.js
gives output:
development
nah
development
instead of
development
im here
By the way, if I'll just manually set var env = 'development' then it work as it should be.
express 4.11.2, node 0.12.0, win8 x64.
I got same problem on windows mode. I'm not sure on linux. This problem caused by spaces between word "development" with "&" character. You can fix by remove spaces on your command. Example:SET NODE_ENV=development& node server.js
Your code looks fine, therefore the reason the equality test must be failing is because the strings aren't equal. Make sure you don't have any extra characters like spaces in your environment variable development string.
same problem, and I find using env.includes('development') instead is okay.
I tried going with the recommendations here but nothing managed to rid me of the wayward space.
so I just trim the variable where it needs to be used:
require('dotenv').config();
const configSet = () => {
const envData = process.env;
console.log('configSet -> process.env', envData);
console.log('configSet -> envData.NODE_ENV', envData.NODE_ENV);
const prodOrDevMode = envData.NODE_ENV.trim();
switch (prodOrDevMode) {
case 'development':
envData.TABLE_NAME = envData.DB_TABLE_DEV;
return envData;
case 'production':
envData.TABLE_NAME = envData.DB_TABLE_PROD;
return envData;
default:
throw new Error('Incorrect env setting');
}
};
const config = configSet();
module.exports = { config };
I'd appreciate any feedback on this in particular if this may cause issues

Meteor.js - Production Meteor.settings throws TypeError undefined

I am new to Meteor, and am setting up dev, stage and production Meteor.settings.
Everything works fine on my local system using the "development" settings, but when I bundle it, and run on Digital Ocean, it breaks. If I removed the call to the settings file, and replace it with the text string, everything works fine.
Here is the settings file, named "1_settings.js" to load before all other js files (in theory at least?):
console.log("=> inside 1_settings.js");
environment = process.env.NODE_ENV || "development";
var settings = {
development: {
public: {},
private: {
"firstUser": {
"id": "ZsKaw3kSbQ4uSvzJg"
},
}
},
staging: {
public: {},
private: {}
},
production: {
public: {},
private: {
"firstUser": {
"id": "oPMfpAuwQ3nuTdpTA"
},
}
}
};
if (!process.env.METEOR_SETTINGS) {
console.log("=> No METEOR_SETTINGS passed in, using locally defined settings.");
if (environment === "production") {
Meteor.settings = settings.production;
} else if (environment === "staging") {
Meteor.settings = settings.staging;
} else {
Meteor.settings = settings.development;
}
// Push a subset of settings to the client.
if (Meteor.settings && Meteor.settings.public) {
__meteor_runtime_config__.PUBLIC_SETTINGS = Meteor.settings.public;
}
}
Here is where I use the settings:
if(Meteor.isServer) {
var settings = Meteor.settings.private;
console.log("=> settings: " + JSON.stringify(settings));
Meteor.startup(function () {
// bootstrap the admin user if they exist -- You'll be replacing the id later
if (Meteor.users.findOne(settings["firstUser"]["id"]))
Roles.addUsersToRoles(settings["firstUser"]["id"], ['admin']);
As you can see, it's breaking on the second "if" statement of the above code, where I'm calling settings["firstUser"]["id"], as shown in the error below:
TypeError: Cannot read property 'firstUser' of undefined
at app/server/app.startup.js:8:42
at /home/qdev/bundle/programs/server/boot.js:175:5
/home/qdev/bundle/programs/server/node_modules/fibers/future.js:173
throw(ex);
^
Obviously, I understand that the settings property is undefind, or null. What I don't understand is why? Even if I didn't set the $NODE_ENV=production (which I have), it should still fall back to the development settings. Help is appreciated!
You are using Meteor.settings wrong. It supposed to be filled by meteor itself with runtimesttings you specify.
To do this you should create a JSON file containing your setting then use the --settings #pathtofile# parameter when calling meteor for development. Make sure it's valid JSON!
This will properly fill Meteor.settings and also makes you able to change settings later.
On the server you use a env variable to point to the settings file. Eventedmind made a video about how to set this up: link

gulp.js+browserify: Dynamically generate development-specific files

I have an application that has some development-specific debugging code in it. Currently, all development code is guarded by a variable called dev at the top of the file. Here's an example of what my app does:
var dev = true;
if (dev) {
console.log("Hello developer");
} else {
console.log("Hello production");
}
When I go to deploy my application, I have to manually change the dev variable form true to false. This sucks.
I'm in the middle of migrating from hand-rolled builds to gulp.js and I want to solve this development vs. production build problem cleanly. I'm thinking about the following:
// Inside main.js
var dev = require('./isdev');
if (dev) //...
// Inside isdev.js:
module.exports = true;
Now, when I build for production, instead of manually setting the dev flag to false, I want to replace isdev.js from module.exports = true; to module.exports = false;. My specific question is, how do I automate gulp such that gulp development produces a file with dev = true and gulp production produces a file with dev = false.
Here's an update to those who are curious.
First, I have an options.js:
exports.dev = false;
I also have a options_dev.js:
exports.dev = true;
Inside of gulpfile.js, I have the following code that parses input arguments:
// Parse the arguments. Use `gulp --prod` to build a production extension
var argv = parseArgs(process.argv.slice(2));
var dev = !argv['prod']; // Whether to build a development extension or not
Finally, when I pipe to browserify, I have the following:
var resolve = require('browser-resolve');
// ...
.pipe(browserify({
debug: dev,
resolve: function(pkg, opts) {
// Replace options.js with options_dev.js if this is a dev build
if (dev) {
opts.modules['./options'] = 'src/options_dev.js';
}
return resolve.apply(this, arguments);
}
}))
The magic happens by using a custom resolve function, dynamically swapping ./options with options_dev for development builds. The browserify docs say:
You can give browserify a custom opts.resolve() function or by default it uses browser-resolve.
When we run gulp, we build a development version. When we run gulp --prod, we build a production version. The value of require('./options').dev allows us to dynamically change things like server endpoints, etc. Cool!
The way that I've seen this done is to set the environment variable on the command line before the execution command. An example of doing this with the Node.JS CLI (in a bash-like environment) would be:
ENV=dev node
> process.env.ENV
'dev'
Then in your code, you could do:
var dev = process.env.ENV === 'dev'
So with gulp, you could use:
ENV=dev gulp <task name>
I tested this out with the following snippet, and it works:
gulp.task('dev', function(){
if (process.env.ENV === 'dev')
console.log("IT WORKED");
else
console.log("NO DICE");
});
Edit:
You can write out the environment to the file isdev right before building:
var fs = require('fs');
gulp.task('build', function(){
if (process.env.ENV === 'dev')
fs.writeFileSync('isdev', 'module.exports = true');
else
fs.writeFileSync('isdev', 'module.exports = false');
// kick off build
});
Now, the correct value will be present in isdev for any require call in the built bundle. You could extend this to other specified environments as well (or to other configuration flags).

How can I specify different config files in Node.js?

try
config = JSON.parse(fs.readFileSync('./config.json', 'ascii'))
catch e
util.debug("Could not parse configuration file.\n" + e.stack)
return
I have that in my node.js code and I have two config files"
config.json.prod
config.json.local
How can I specify that it should run the .local?
By the way, I'm using CoffeeScript
Yea, you certainly can. Checkout nodepad (great reference app):
https://github.com/alexyoung/nodepad/blob/master/app.js
The source comes from this blog series: http://dailyjs.com/2010/11/01/node-tutorial/
Edit: For example
if (app.settings.env == 'production') {
mailer.send(mailOptions,
function(err, result) {
if (err) {
console.log(err);
}
}
);
}
he uses app.settings.env to swap out different environmental/app settings. Same could be used to load a config file. – Chance

Resources