Uglify the global variable

2.7k views Asked by At

I have an app in nodejs. In it, I define some global variables that are shared across multiple files. For example:

//common.js
async = requires("async");
isAuthenticated = function() {
  //...
  return false;
};

//run.js
require("common.js");
async.series([function () {
  isAuthenicated();
}], function () {
  console.log("done");
});

I want the async and isAuthenticated variables to be minified, but minified to the same thing in all files. It would look like the following:

//common.min.js
a = requires("async");
b = function() {
  //...
  return false;
};

//run.min.js
require("common.js");
a.series([function () {
  b();
}], function () {
  console.log("done");
});

How to do it in uglifyjs?

I'm currently looping through the files and using the command uglifyjs $file -m "sort,toplevel" -c > $file.min on each.

4

There are 4 answers

0
Keenan Lidral-Porter On

You would want to concat the files before you go ahead and uglify them. Concatenation is the process of combining multiple files of code into one monolithic creature that knows everything about all parts of your code. This is often done in conjunction with uglyfying for several reasons, mainly for performance benefits (your app runs a lot faster if you only send 1 file to the client).

That being said, this is typically a practice that is done when your serving code to a client, not necessarily for back-end / server-side logic. Ideally no one but you or people with access to whatever service you're using to deploy said server code should see that side of your code. If your main concern is to prevent reverse-engineering, or make your code unreadable, I suggest obfuscating your code.

"This is omega site. Best encrypted level he has. Looks like obfuscated code to conceal its true purpose. Security through obscurity." - Q Skyfall 2012

0
punund On

If your globals are confined to common.js, you may try

uglifyjs --define-from-module common.js $file...

and remove require()s.

0
surui On
  • Don't use globals.
  • Use var async = reuqire('async') where needed.
  • Use module.exports in your specific modules you require.
  • Use something like browserify to generate a single js.
  • Uglify (or use a browserify transform named uglifyify)

For example, the simplest form (without using uglifyify)

$ browserify run.js | uglifyjs -c > run.min.js

Note that if you use your own code, like common.js, you should require it using a relative path, var common = require("./common").

I suggest you use the exports syntax:

// common.js code

exports.isAuthenticated = function() {
  //...
  return false;
};

And of course use it just as you would with async.js:

//run.js
var common = require("./common");
var async = require("async")
async.series([function () {
  common.isAuthenicated();
}], function () {
  console.log("done");
});

assuming both common.js & run.js reside in the same directory.

related question: How to get minified output with browserify?

A Side Note

The way you used async.series in your question has no real advantage. You could have just:

//run.js
var common = require("./common");

common.isAuthenicated();
console.log("done");

in Async series you usually call async functions:

async.series([
    function(callback){
        // do some stuff ...
        callback(null, 'one');
    },
    function(callback){
        // do some more stuff ...
        callback(null, 'two');
    }
],
// optional callback
function(err, results){
    // results is now equal to ['one', 'two']
}); 

so, I would expect to see something like:

// common.js code

exports.isAuthenticated = function(callback) {
  //...
  callback(null, false);
};

and then

//run.js
var common = require("./common");
var async = require("async")
async.series([common.isAuthenicated], function (err, results) {
  console.log("done with", results[0]);
});

I usually prefer a different "syntax"

// an example using an object instead of an array
async.series({
    one: function(callback){
        setTimeout(function(){
            callback(null, 1);
        }, 200);
    },
    two: function(callback){
        setTimeout(function(){
            callback(null, 2);
        }, 100);
    }
},
function(err, results) {
    // results is now equal to: {one: 1, two: 2}
});

But it's your call. The async examples were taken from https://github.com/caolan/async#seriestasks-callback

0
akrsmv On

In NodeJs there is the concept of defining global variables like posted in this thread:

global.myGlobalVar = "something visible to all modules";

I am too using uglify in my node apps, and it turned out that when using global.xyz, xyz does not get uglified.

disclaimer: I am totally aware that exposing global info is an anti pattern. But sometimes there is a good reason for it.

Hope that helps!