Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 794
advait Avatar asked May 09 '14 22:05

advait


2 Answers

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!

like image 97
advait Avatar answered Nov 06 '22 16:11

advait


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).

like image 31
aelr Avatar answered Nov 06 '22 15:11

aelr