Ways to Remove Those Pesky console.log Statements
December 9, 2013
The Problem
Have you ever published your code only to find pesky console.log
statements littering your web application? These can be problematic for several reasons...
- It is embarassing to have logs in the console
- It can slow down the page's performance
- It causes bugs in IE8/9 when the devtools are not open
So then, what are some ways you can protect yourself from all those logs?
1: Manual Removal
The lowest tech solution is to go through your code-base and manually remove all instances of console
statements. This includes variations such as console.log
, console.dir
, console.group
, etc...
Pros
- The
console
statements are completely removed from the code base and are not slowing down the system or increasing code size.
Cons
- Manually removing these statements can be laborious and annoying
- You may want to leave some
console
statements to help track down issues during development
2: JSLint/JSHint/ESLint
This doesn't really remove console
statements from your code, but by using a linting tool it can help you identify where they are and possibly stop your build process.
JSLint/JSHint have a devel
option that you can turn on and off. The intent of devel
is to define globals (alert
, console
, etc) and allow you to use those during development. The idea is to turn off this setting when building to production to pinpoint areas of concern.
If you use ESLint, the no-console
has the same effect. It will disallow the use of console
.
Pros
- It will enable you to isolate where your
console
statements are in your codebase - You can change this JSLint/JSHint/ESLint option between your development and production build process
Cons
- There is still a manual process of removing the
console
statements
console
3: Monkey Patching The following code snippet is a console monkey patch from the HTML5 Boilerplate.
This code overrides the native console
object with noop
methods (functions that don't do anything). If console
doesn't exist then a mock version is created.
// Avoid `console` errors in browsers that lack a console.
(function() {
var method;
var noop = function () {};
var methods = [
'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
'timeStamp', 'trace', 'warn'
];
var length = methods.length;
var console = (window.console = window.console || {});
while (length--) {
method = methods[length];
// Only stub undefined methods.
if (!console[method]) {
console[method] = noop;
}
}
}());
Pros
- Monkey Patching is very easy to implement and takes minimal time to implement
Cons
- The
console
statements are still present in the code causing slower processing and increasing overall file-size
4: Using a Library
Accidentally leaving extra console
statements isn't a new problem. It's been an front-end issue for quite some time. Because of this, there have been sever JavaScript libraries to help assist with the issue.
Ben Alman (@cowboy) developed the JavaScript Debug library in order to build a wrapper around the console
object. His library provides a cross-browser way to provide logging. It passes through natively supported functions and also falls-back accordingly.
debug.log( "test" ); // Level 1
debug.debug({ msg: "test" }); // Level 2
debug.info( false ); // Level 3
debug.warn( 42 ); // Level 4
debug.error( [1, 2, 3] ); // Level 5
In addition, each method has an associated debug level associated with it. The nice thing about this is that you can control how much or little you want to see in your console. For example, if you don't want to see any logging then you can specify a debug level of zero... debug.setLevel( 0 );
Pros
- Provides a nice abstration layer around the
console
, which isn't supported in all browsers - Enables different levels of debug messages
- Will collect logging results (even if
debug.setLevel( 0 )
), allowing you to open the console and "replay" previous log statements - You can redirect where the logs are displayed (Firebug Lite, inline logging, etc...) by using
debug.setCallback
Cons
- Even if you set debug level zero, the statements still remain in the source code and can clutter and impede performance
5: Using UglifyJS
You can also remove console.log
statements by using the Uglify2 minifier! I ran across an interesting blog post by John Dewar (@jstarrdewar) entitled Use UglifyJS To Automatically Strip console.log() From Your Production JavaScript.
The Gist of the technique is that you'd include the statement if (typeof DEBUG === 'undefined') DEBUG = true;
in your application somewhere and then prepend DEBUG
to your console
statements, e.g. DEBUG && console.log("test");
When you are in the development DEBUG
won't be defined and so DEBUG
will be defined to true
, therefore, the console
statements will execute.
if ( typeof DEBUG === "undefined" ) DEBUG = true;
function sayHello() {
DEBUG && console.log( "Hello World!" );
}
However, if you tell Uglify2 to compress and define DEBUG
to false
then the minifer will clean up and remove the statements that can not execute.
# Uglify
uglifyjs --define DEBUG=false "hello.js" > "hello.min.js"
# Uglify2
uglifyjs --compress --define DEBUG=false hello.js -o hello.min.js
Pros
- You can integrate this as part of your build process
- You can choose to keep some of the console statements by not prepending
DEBUG &&
- You are only chaning the build output
- The console statements will be completely removed
Cons
- This technique may not work with all minification tools
- It is a little cumbersome to add the addition
DEBUG &&
check
NOTE: Since writting this blog post, Mihai Bazon (@mcbazon) has added a new option to the Uglify2 minifer (
drop_console
) that will discard calls toconsole.*
functions! Thanks Mihai ;)
6: Using Grunt
If you use Grunt as your JavaScript automation tool, then you are in luck... there is a grunt task to help you manage console
statements.
Eric Hynds (@erichynds) has created the grunt-remove-logging task to remove unwanted console
statements.
There are several options you can provide the task, such as:
replaceWith
- Value to replace logging statementnamespace
- Object logging methods are attached tomethods
- Array of method names to remove
There are some times when you actually might want some log statements to keep around. In that case you can append your code with /*RemoveLogging:skip*/
to let grunt-remove-logging
know that you want to skip (not delete) that log statement.
Here is an example JavaScript snippets with some console.log
statements littered throughout.
(function( etm, undefined ) {
var myVariable = 0;
console.log( "test 1" );
etm.init = function() {
console.log( "test 2" );
myVariable += 1;
};
function secret() {
console.log( "test 3" );
myVariable += 2;
};
}( window.etm = window.etm || {} ));
In order to use the grunt-remove-task
, you'd install it (npm install grunt-remove-logging --save-dev
) and then include it in your Gruntfile.js
like the following...
module.exports = function( grunt ) {
grunt.initConfig({
pkg: grunt.file.readJSON( "package.json" ),
removelogging: {
dist: {
src: "src/<%= pkg.name %>.js",
dest: "build/<%= pkg.name %>.clean.js",
options: {}
}
}
});
grunt.loadNpmTasks( "grunt-remove-logging" );
grunt.registerTask( "default", ["removelogging"] );
};
And then once you run grunt from the command-line you'll get console-free output like the following...
(function( etm, undefined ) {
var myVariable = 0;
etm.init = function() {
myVariable += 1;
};
function secret() {
myVariable += 2;
};
}( window.etm = window.etm || {} ));
Note: If this task doesn't quite fit your needs, there is another Grunt task called grunt-strip written by Jarrod Overson (@jsoverson) that you might find interesting.
Pros
- You can integrate this as part of your build process
- You can choose to keep some of the console statements if you have a need
- You aren't overriding existing code, but modifying the origional source code, but only the built version
- The empty removed statements will get cleaned up by the minification process (Uglify2, etc)
Cons
- This relies on using Grunt as your automation tool
The Solution
If you are anything like me, you've accidentally left a console.log
statement in your production code. By using one of the above techiques hopefully you can reduce keep this from happening again.
If you know of any other techniques, please feel free to add a comment and share. Thanks!
Tweet about this post and have it show up here!