Chrome dev tools deep dive : Network


1. Throttling

A web application might work beautifully on fast networks but stutter and even throw up bugs on slow connections. Fiddler used to be the go-to tool for simulating delays and adding latency during testing; the good news now is that Chrome provides throttling too.

There are preset profiles available (e.g. GPRS, 3G, etc.) but you can define custom latency and throughput profiles if you want. Something for those of us who want to simulate network connections to IoT devices.

throttle

2. Replay requests

At times, there is a need to replay an isolated request several times. Refreshing the page works but brings down the entire page payload again.

A better alternative would be to find the request in the network tab, right-click on it and then replay it. Note that if you want more control, for example, if you want to replay a  request 10,000 times, you might have to look at other tools like fiddler or curl.

replay

3. The network panel headers

The default tabs that appear on the header row can be changed. For example, you can display the Method, eTags or even cookies columns.

Clicking on a tab header sorts all the rows by that column. Unfortunately Chrome doesn’t allow you to reorder the header ordering; a pity as I would love to customize tab ordering.

tabs

4. Network performance and content compression

This is one useful tool that is not so obvious. If you have the ‘small request rows’ option set; then you’ll have to switch to ‘large request rows’ (See the gif below).

  1. Size and Content: Size shows the magnitude of the downloaded file over the wire while content shows the real size of the contents. Ideally, size should be smaller than content since browsers can handle gzip-compressed files. If you see requests that have the same size and content value; that’s an optimization hole to plug.
  2. Time and Latency: The time row shows the request’s entire round trip time while the latency row shows the time it took to set up a connection and process the request on the server. If request latency times consistently take about 80 – 90% of the total time, there might be server processing or network connection investigations required.

optimize

5. Debugging with HARs

A customer living in Antarctica reports a bug in your web app. Obviously you can’t go to Antarctica, yet you need a dump of the customer’s state. Don’t fret it; HARs provide a way out.

HAR means HTTP Archive – a JSON file containing all the information necessary to recreate the network tab experience.

So, you tell the customer to open up the Chrome network tab, export the HAR file and send to you. There are lots of HAR readers available or you can set up your own via npm. Problem solved!

hars

6. Examining HTTP traffic

Clicking on a request in the tab opens up a new panel which allows you to examine the request’s details. You can see all the headers; responses, cookies timelines etc. The preview option offers a nice prettified output for response data and if you prefer the plain view; that does exist too.

examine

7. The Filmstrip

The filmstrip generates a frame-by-frame sequence of screenshots showing the page render process during load. It also includes timing information so you can figure out what the bottlenecks are.

For more accurate results; disable the cache and then refresh the page. You can read more about the filmstrip here.

filmstrip

8. Others

  • Disable the cache: Disables the cache to ensure a fresh load
  • Filter: Allows you to type expressions to filter network request rows. There are also out-of-box filters for XHR, JS, etc. I like the websockets (WS) option a lot.
  • Preserve log: Don’t wipe the log on refresh
  • Copy support: Allows you to copy  a request; exposes cURL as a copy option too. Yay for cURL users!

Here are other posts in this series:

Chrome dev tools deep dive : Sources


The Sources tab provides the ‘IDE’ experience. It provides a wide variety of features ranging such as live editing of code via workspaces, debugging and snippets.

Some tips and tricks follow:

1. Pretty print

Want to prettify that minified JS or CSS? The format button works ‘pretty’ well (pun intended).

prettyprint

2. Snippets

Although it is easy to just type away quick implementations in the console tab, the console has poor editing capabilities. A typo or single change necessitates editing the entire typed code.

Another approach involves creating a scratch file and copy-pasting changes to the console for execution. It works better than console editing but still requires some work.

The snippets tab offers the best solution. You edit, save and run code from one spot. Even better still, there is a curated collection of useful snippets; why not stand on the shoulders of giants?

snippets

3. Shortcuts

These are a couple of shortcuts to make debugging much more fun.

  • CTRL + D: Finds the next occurrence of the selected text in that window. Useful during search as an alternative to CTRL + F. Also useful for multi-editing all occurrences simultaneously.
  • CTRL + M: Useful for jumping between matching function braces.
  • CTRL + O: Opens up a file drawer that you can search for specific files using a ‘sublime-like’ fuzzy matching interface. CTRL + P also works.
  • CTRL + SHIFT + O: Opens up a drawer for all the functions in the open file. Useful for jumping between function definitions in a file. CTRL + SHIFT + P also works.
  • CTRL + SHIFT + F: Searches across all files. Exposes regex + case sensitivity options too.
  • CTRL + F: Searches current file
  • CTRL + G: Jump to line number

4. Conditional Breakpoints

Setting a breakpoint is straightforward but what if you only want execution to stop when certain conditions are met? Easy-peasy, right-click on the breakpoint and write an expression. Whenever the expression is truthy; the breakpoint will be activated.

The chrome engine evaluates the expression to determine whether to break or not. What happens if there is a falsy expression that changes the live code?

There! That’s a trick for modifying the live production code during debugging – you can overwrite variables, change functions or even throw Exceptions. Just make sure your expression is falsy (or truthy if you want to break at that point). Want to turn declarations into expressions? Read about the IIFE.

breakpoints

5. Function definition

Do you know you can jump to a function’s definition directly? Before discovering this feature, I used to use invoke toString as a poor substitute for reflection or do a global find.

Chrome has a good solution to this, right-click on the function and jump to its declaration – very useful when navigating around in big huge code bases. It also works for functions that appear in the stack window.

fxnDef

6. XHR Breakpoints

This class of breakpoints allow you to set specific breakpoints based on the endpoint URL which is very useful when debugging code involving endpoints.

Also remember to check the Async option so the call stack includes asynchronous operations e.g. AJAX calls, timeouts.

breakpoints

7. Exceptions

You know there is a bug somewhere but can’t find it. The ‘Pause on exceptions” option is very useful for exactly such scenarios.

Checking the “Pause on caught exceptions” checkbox means that even properly handled exceptions will still trigger a debugger stop. This has been very helpful for tracking down hard-to-find bugs.

exceptions

8. Blackboxing

Black boxed code will be ignored and hidden during debugging. Stepping into functions defined in blackboxed scripts is a no-op. This saves you time from walking into the pits of external library call stacks.

I nearly always blackbox external libraries (e.g. jQuery, AngularJS etc). Otherwise, the debuggger  is activated for exceptions thrown in external code. And as we all know, if there is a bug, it is most likely from our code.

tldr: use the blackbox to hide external scripts.

blackbox

Enjoyed this? Here are some more posts in this series:

  1. Chrome dev tools deep dive : Elements
  2. Chrome dev tools deep dive : Console
  3. Chrome dev tools deep dive : Network

Chrome dev tools deep dive : Console


The console is one of favorite places. The REPL environment is a quick way to validate JavaScript expressions. However, there is a lot more it can do. Read on.

1. $0 – $4 selectors

The last inspected element is always available in the console as $0. $1 points to the next most-recently element and so on. AngularJS developers can leverage this to retrieve the scope of elements by invoking angular.element($0).scope().

Want to inspect the DOM element? Right-click on it and select reveal in ELEMENTS panel.

selectors

2. Monitor

The monitor function is useful for tracing function invocations and parameters. Note that for reference types (e.g. objects), the logs show [Object object] – probably due to calling toString on values. Primitive values are all good.

monitorTurn off tracing with unmonitor or by refreshing the page.

3. MonitorEvents

Allows you to monitor events that happen on particular DOM elements. The first parameter is the DOM element to log event information for while the second parameter is the event (or array of events) to track. If this is undefined, then all events on that object will be logged.

As usual, deregister with unmonitorEvents.

monitorEvents4. Debug

Calling debug on a function would break invocation as soon as that function is invoked. This is very useful for those one-liners or for debugging external libraries. Calling undebug removes the breakpoint.

Note: What if some external library overrides debug? Ideally namespaceing should be used to avoid overriding globals; however, all the command line API functions are accessible via the __commandLineApi object. Try examining the object in your console.

debug

5. Table

console.log works great but makes it difficult to view tabular information. Enter console.table (table)  to the rescue. It accepts property names as extra parameters for filtering out unwanted columns.

table6. Keys and Values

For accessing the keys and values of objects. Combine with table for even more fun!

keys

7. Others

Want to preserve logging even when you reopen the tab? Check that box. Want to target a specific iframe? Select it from the drop down. Want to clear the log? Click the Ø button or use CTRL + L.

MISC

And that wraps it up!

Enjoyed this? Here are some more posts in this series:

  1. Chrome dev tools deep dive : Elements
  2. Chrome dev tools deep dive : Sources
  3. Chrome dev tools deep dive : Network

Chrome dev tools deep dive : Elements


1. Search

CTRL + F allows you to search for strings in the DOM but you can also search using CSS selectors and XPath expressions.

searchElements

2. Color picker

Ever wanted to figure out what colours exist on a web page? Or prefer some other colour format?

Here comes the color picker:

  • Shift click on the color box to change colour formats (e.g. hsl, rgb)
  • Pop up the color picker by clicking on the box

colorPicker

3. Force Element State

You want to inspect the hover style of some DOM element – you can hover over it but you lose the pseudo-state as soon as you exit the element boundaries. A better way is to force the element into the desired state.

There are two ways:

  • Right-click the element
  • Using the styles panel

forceState

4. Drag / Drop elements to new positions

Want to quickly move some element to some new location? So drag drop it. This comes in handy for issues relating to z-indices and ordering.

dragdrop

5. Debug on DOM modifications

This allows you to break whenever a DOM element or its children are modified. Very useful for debugging dynamically-injected DOM elements. There are three possible options:

  • Subtree modifications – DOM hierarchy changes under the chosen node (e.g. child insertions and deletions)
  • Attributes – inline style changes, attribute changes, animations
  • Node removal – when the node is deleted

You can use the DOM breakpoints tab to view all such breakpoints.

When an event triggers the breakpoint, the browser will stop at that point. This is nearly always jQuery; you can then walk up the stack to find the code that triggered the DOM modification.

DOMBreak

6. The Styles tab

Allows you to edit existing CSS styles, add new ones and also view the source. CTRL + Click on a particular rule will open it up in the sources definition. Clicking on the full style too will open up that file.

styles

7. Computed Styles

This shows the active styles applied to an element. It also comes in handy for figuring out what rules come from the browser’s default stylesheet.

To see all the applied rules on an element, check the show all checkbox and it expands. It’s also a very good way to learn more CSS.

computed

Enjoyed this? Here are some more posts in this series:

  1. Chrome dev tools deep dive : Console
  2. Chrome dev tools deep dive : Network
  3. Chrome dev tools deep dive : Sources

How to watch variables in JavaScript


We all have to track variables while debugging; generally the easier it is to monitor changes, the faster bugs can be detected and fixed.

Web developer tools expose various methods for tracking changes in variable values. There are a couple of drawbacks e.g. non-uniform support across platforms) but again, half-bread is better than none :).

Curious about such methods? Let’s take a walk…

1. Chrome’s Object.Observe

First on the list is Chrome’s Object.observe static method. The observe/unobserve functions are static functions – they can only be called on Object and do not exist on object instances. Lets take an example:

var obj = {};
Object.observe(obj, function(changes) {
    console.log(changes[0]);
});

obj.val = "Hello"

// [{  name: "val",
//     object: { val: "Hello" },
//     type: "add" }]

That was pretty cool right? How about observing primitives?

var val = 2;

Object.observe(val, function(changes) {
    console.log(changes[0]);
});

//Console
//TypeError: Object.observe cannot
//observe non-object

Disappointed? Maybe we should check out Firefox’s watch function then…

TIP: Chrome also has experimental Array.observe and Array.unobserve methods. Don’t use in production!

2. Firefox’s Object.prototype.watch method

Firefox differs from Chrome because it exists on object instances; thus any object can watch for changes to its inner variables. Confused? Lets see an example:

window.val = 2;
//equal to var val = 2;

window.watch("val",function(id, old, cur) {
 console.log("Changed property: ", id);
 console.log("Original val: ", old);
 console.log("New val: ", cur);
});

val = 4;

// Changed property: val
// Original val: 2
// New val: 4

Advantages? Well, you can now watch primitives values. I also like the fact that object instances can watch their own properties for changes rather than having a global static watcher. But then again, it’s up to you :).

3. Can I haz polyfill?

A few browsers (including IE) do not have support for watch or observe; sometimes you do not have the free choice of selecting a browser, so let’s move on to finding an implementation that can be used as a polyfill and work across browsers.

First, lets talk about getters and setters in JS; JavaScript has the concept of getters and setters which allow you to define functions that are invoked when you try to retrieve a value or set its value.

var obj = {};

Object.defineProperty(obj, "name", {
    get : function(){ return this._name;},
    set: function(val){  this._name = val;}
});

obj.name;
//undefined

obj.name = "name";
obj.name;
//name

TIP: Can you figure out the bug in the following snippet?

var obj = {};

Object.defineProperty(obj, "name", {
    get : function(){ return this.name;},
    set: function(val){  this.name = val;}
});

obj.name;
//What happens?

Just as you thought, how about using this concept to fix this issue? Various browsers implement the getter/setter syntax differently, IE expects this format while Chrome expects this format. You could write a façade to hide this but again there is ugliness lurking around under the covers.

But great news! There is an excellent 5-year old polyfill by Eli Grey and it might meet your needs. Here is the gist and lets dive into its brilliance.

if (!Object.prototype.watch) {
 Object.defineProperty(
   Object.prototype,
   "watch", {
     enumerable: false,
     configurable: true,
     writable: false,
     value: function (prop, handler) {
       var old = this[prop];
       var cur = old;
       var getter = function () {
          return cur;
       };
       var setter = function (val) {
        old = cur;
        cur =
          handler.call(this,prop,old,val);
        return cur;
       };

       // can't watch constants
       if newval(delete this[prop]) {
        Object.defineProperty(this,prop,{
            get: getter,
            set: setter,
            enumerable: true,
            configurable: true
        });
       }
    }
 });
}

How it works?

The function assumes knowledge of JavaScript’s accessor support (surprised that JS has getters and setters, yes there are subtle pockets of beauty in the language). The object.watch polyfill function accepts a property to watch and a handler to call when that function changes.

The handler function uses a beautiful trick – it redefines the watched value in the same scope, this ensures that the handler is always invoked when that value changes.

The trick to understanding the polyfill is in the second Object.defineProperty call. The value to be watched is first deleted to verify it is not a constant but this deletion will remove it from the scope. To counteract this, Eli’s brilliantly redefines the object in the same scope using Object.defineProperty. The getter is a plain getter while the setter is more involved – when the watched value is overridden or set to a new value, the setter is called. The closure in the watch object will invoke the handler after setting property to its new value. Neat huh?

Conclusion

Tip: A good way to debug is to use the debugger with an observed variable as shown below:

Object.observe("value", 
   function() { debugger; });

This will cause the debugger to kick in whenever the value changes and this helps a lot in tracking down bugs.

1. Eli’s polyfill didn’t fire in a deterministic manner when I tried it on Chrome but it did work.

2. Remember there are going to be performance implications but again this assumes you are in debugging mode 🙂

And that’s it! Feel free to copy over Eli’s implementation and use for your code.