Beyond console.log

Making the most of your developer tools

Session Agenda

Session Goal

Spark the 🔥 in your 💗 to explore your dev tools

Who am I?

Who are you?

like follow subscribe at
brianloveswords.github.io/srccon-2016

shift+click to execute code blocks

if shit gets weird, refresh the page

Opening up DevTools

View → Developer → Developer Tools
Command + Option + I

Clearing the Console

clear()
Control + L

console.log()

Alternate call signatures & formatters


// Old standby
console.log('this is normal');
        

// Can take multiple arguments, will separate them with a space
console.log('prefix:', {x: 'some object', y: 10}, 'then some more');
        

// Displaying element as HTML vs as an object
console.log('HTML (%o) vs Object (%O)', document, document);
        

// Styling with CSS!
console.log('%ca friggin travesty', 'font-size: 10em; color: red;');
        

console.dir()

Alias for console.log('%O', thing)

When I'm logging objects, I tend to use this over console.log because I usually want to inspect properties and I care less about HTML representation.


// Explore the HTML contained in the document
console.log(document);

// Explore the JavaScript properties attached to the document object
console.dir(document);
        

console.info()
console.warn()

Some preset style, useful with filters


console.info('this is some information that might be useful, whatever');

console.warn('this could be an issue');

console.warn('%calso supports formatters', 'color: #f0f');
        

console.error()
console.trace()

Stack traces!


let foo = function() {
  console.info('entering foo');
  bar();
}

let bar = function() {
  console.info('entering bar');
  baz();
}

let baz = function() {
  console.info('entering baz');
  console.trace('from baz');
  console.error('this should not have happened');
}

foo();
        

console.group()
console.groupCollapsed()

Group logs into a collapsable object


// Until console.groupEnd() is called, every `console.*` call
// will end up in a collapsable group.
console.group('do the stuff');
console.log('this is how we do it');
console.trace();

// Groups can be nested & formatters work!
console.groupCollapsed('do more stuff');
console.info('this is some information');
console.error('oh shit');
console.groupEnd();

console.log('one last thing from the outside group');

// Always make sure to end your groups
console.groupEnd();
        

async, blegh


// Not ideal imo

setInterval(_ => {
  console.group('time1');
  console.log('this is a member of time1');
  console.groupEnd('time1');
}, 997);

setInterval(_ => {
  console.group('time2');
  console.log('this is a member of time2');
  console.groupEnd('time2');
}, 911);
        

A solution I have used


let debug = function (prefix, msg, ...rest) {
  // Short-circuit on production. Use a build system
  // system to include a script that sets this global state.
  if (window.ENVIRONMENT === 'production') {
    return true;
  }

  let style = 'font-weight: bold; color: #dcd;';

  console.log(`%c:${prefix}:%c ${msg}`,
              style, '', ...rest);
}

setInterval(_ => debug('noise', Date.now()), 2000);
setInterval(_ => debug('module1', 'this is something, eh? %O%', document.body), 3000);
setInterval(_ => debug('module2', 'something unrelated'), 4000);
setInterval(_ => debug('module3', 'definitely aliens on the ship'), 5000);
        

console.time()
console.timeEnd()


console.time('social-construct');

// Multiple timers are totally fine as long as
// they have different names
console.time('message')
console.info('time is a social construct');
console.timeEnd('message')

setTimeout(_ => {
  console.info('%c...or is it?', 'font-style: italic');
  console.timeEnd('social-construct');
}, 2000)
        

console.table()

Sortable data in the console


// Remember to turn on async stack traces

fetch('albums.json')
  .then(response => response.json())
  .then(albums => {
    // Show everything
    console.table(albums);

    // Show only selected fields
    console.table(albums, ['year']);
  })
  .catch(e => console.error(e))
        

💸 Cache Problems 💸

debugger


// This program is broken, let's find out why
let foo = function(input) {
  console.info('entering foo, once again');
  bar(`${input} ${input}`);
}

let bar = function(input) {
  console.info('entering bar, pump up the world');
  let parts = input.split(' ');
  parts.push(parts[0]);
  baz(parts.join(' '));
}

let baz = function(input) {
  console.info('entering baz, watch my flow');

  console.log(`🎶 ${input} you know that I'll be back 🎶`);
}

foo('return of the mack');
        

Pause On Exception


  // Make sure to turn on Pause on Exception first
  let x = {howDoWeDoIt: this};

  console.log('this is gonna happen');

  undefined('i bet this is a function');

  console.log('never gonna get here');
        

console.assert()


let x = {howDoWeDoIt: this};

console.assert(1 == 1, 'somehow math stopped working');

console.assert(1 == 2, 'yep I guess math did stop working');

console.log('assert does not cause abrupt completion');
        

Event Listener Breakpoints


document.body.addEventListener('mouseup', event => {
  // remember to go into the Sources tab and turn on the mouseup
  // event listener breakpoint. When it breaks, execution will be
  // paused within this context.
  let time = Date.now();
  let element = event.target;
  console.log(`${time}: %O`, element);
});
console.info('event listener added');
        

blackboxing


// This function is provided by the hot new 10x framework, 'chaos.js'.
// It flips a coin and `throws` some unwanted saxophones on heads

// To blackbox this dumb, dumb script, go to devtools settings,
// look for "blackboxing" on the right navigation.
chaos();
        

Standardization

For a long time there was no standard for the console API. There is an effort to change that going on at github.com/whatwg/console

Also see
node-inspector

💗