Chrome DevTools

First a note on the drawer. It isn’t one of the panels but it’s there for us whenever we ask for it (esc). We’ll cover the ‘Console’ and ‘Emulation’ tabs within the following sections, but not ‘Search’ and ‘Rendering’. ‘Search’ is pretty self explanatory and ‘Rendering’ lets us toggle a few options – play around with it and see what they do when interacting with the page. Interesting! But this isn’t where the main guts of the DevTools are, so on to the main content. Panel by panel, I’ve tried to at least touch on everything, so if there’s anything missing – point it out in the comments at the end!

Elements A view into the structure of our site

With all the complexity and dynamism that tends to be present in modern sites, having a place where we can see and edit the final structure of both the HTML and the CSS is invaluable. There’s not really much more to say in overview – it’s amazing!

DOM Tree The main pane

The main section here shows us the live DOM tree. It shows any updates made to the tree by user interactions or JavaScript and it lets us edit the tree and see our changes reflected in the page! Click around, try dragging to move elements, delete some, add some others, edit attributes, you can do pretty much anything you want in there and see the page update. There’s also a context menu for us to explore: right click on any element in the tree and play around with the options, they’re pretty much self explanatory so I’ll skip to the last one: Break on…

DOM Breakpoints. These will pause execution of any JavaScript based on one of three conditions

  • Subtree modifications: changes to child elements.
  • Attributes Modifications: changes to attributes of only the selected element.
  • Node Removal: deletion of the selected element.

When this happens, DevTools will switch to the Sources panel, open the relevant JS file and highlight the line that hit the DOM Breakpoint. I’ll go over the Sources panel in its own section later in this article (go check it out if you really can’t wait), but for now lets leave that off there and check out the other half of the Elements panel:

Elements sidebar (for lack of a better name) ‘Styles’, ‘Computed’, ‘Event Listeners’, ‘DOM Breakpoints’ – again, and ‘Properties’.

Styles This is the tab that’s usually open for me. It shows the CSS rules that apply to the selected elements in the DOM tree, and they are just as editable. Have a play around if you haven’t already! Be sure to check out the box-model visualization below all these styles – that’s editable too! There’s also three buttons to note here in the top right.

  • New Style Rule: add another style
  • Toggle Element State: change between hover/ visited etc (this is also available in the DOM tree context menu)
  • Animation Controls: play with animation!

The Computed tab shows us the final set of CSS rules that apply to our selected element in the DOM tree. It’s a good resource when an element is picking up large numbers of overriding styles which can be hard to sift through in the ‘Styles’ tab.

Event Listeners is another fairly simple one – click on an element in the DOM tree to the left and see which JavaScript functions are registered listeners on it in this area.

DOM Breakpoints Remember the breakpoints from the context menu in the tree? If you’ve added hundreds of them all over the place, this lists them all out for us. It will also highlight them in the page on hover and let you toggle which should be active.

Properties This shows all the properties of a selected element – this is how JavaScript and the DOM see elements.

One final trick that DevTools has running is a track of all our edits to the CSS. In the ‘Styles’ panel, next to each selector, you’ll see a link to the sheet from which that rule comes from. It links to the specific line of that stylesheet within the Sources panel. Once there, we can right click on the sheet and select ‘Local Modifications’ to see a history of every edit we’ve made in this session. No more need to remember every single change you made in order to replicate them in your working directory, in fact (if it works with your setup) we can right click and ‘save as’ to replace the old sheet in our project with the new one from the browser!

Network Loading performance

If your site is slow, this panel should probably be your first stop. It allows us to record all the communication between your browser and the network. We can see what’s getting loaded, where it’s all getting loaded from and how long each step takes in loading every single resource that is required by your page.

Quick tip: only record individual events and do it in incognito mode – the recordings generate a fair amount of data and any installed chrome extensions tend to add in a bit of noise.

To get started, open the Network panel in DevTools, click the record button (top left), refresh, wait for everything to load and stop the recording. Now we can run through the various things that should have just shown up:

The controls in the top row:

  • Record: start/stop recording.
  • Clear: deletes current recording.
  • Filter: Trim down our list of resources to show the ones we’re interested in:
  • Large / small resource rows: toggles extra data.
  • Timeline: hides the extra data columns for a larger timeline.
  • Preserve Log: only works within a single recording session, stops the log from clearing on navigation.
  • Disable Cache: Stops resources loading from the cache (only while DevTools is open).

The main panel: Here we see our results. The ‘Name’ column is permanent, the others can be shown/hidden by right clicking on their titles and selecting from that menu. You might also have noticed when toggling the timeline control in the very top row that all the extra data columns are shown/hidden – that’s because the timeline is usually the part we’re most interested in and it can get pretty wide! For every column we can also sort the resources, again by clicking on their headers.

  • Left click on the column header: sort by this columns data.
  • Right click on headers: toggle which columns to show.
  • Right click on resource row: to show resource details.

Quick note about the timeline:

  • The blue line: DOMContentLoaded – all the DOM content has been loaded and parsed
  • The red line: the load event – all the sources (images, code) have been fully loaded.

Resource Details. Finally, if you click on one of the resource rows, all the data columns will be replaced by a tabbed panel showing details for the selected resource. (click ‘x’ in the top left to close out this view).

  • Headers: shows us the request and response headers that are included with every resource.
  • Preview: shows the actual resource: code / images / fonts.
  • Responce: shows the unformatted resource.
  • Cookies: if there are any, it shows those that get transmitted.
  • Timing: the breakdown of each step in loading this resource (also shown when hovering on the timeline view)

HAR files (HTTP Archive)
We can save a recording from the network tab as a HAR file (right click on the timeline -> save as HAR…). This can be opened by other developers using the Chrome HAR Viewer. If, in testing, there is a loading performance related issue, this could come in handy in showing someone else exactly what you’ve seen.

Sources Essentially – a live text editor and debugger

The JavaScript we’re writing to run modern Websites (and / or WebApps depending on your view) is now as important (if not more so) than the HTML and CSS that make up the visual components. So while they have the Elements panel, JavaScript needs it’s own way to show us what’s happening on the live site. The Sources panel lets us view the code, un-minify it, set breakpoints, step through/in/out functions and all the other great things that are available through the V8 Debugger. It’s almost like an in browser IDE (almost)!

The best way to see how it all comes together would be to open up one of your own sites with some fun JavaScript (so at least the code that shows up will be familiar), but if you don’t have your own, try this angular demo.

The main layout of this panel: file tree on the left, file tabs in the middle showing file contents, and some debugging tools on the right. The left and right panels can be toggled if you want more space for the code view.

The file tree

We have a few tabs here that let us explore the various .js and .css files that the browser has loaded: ‘Sources’ for your site, ‘Content scripts’ for any chrome extensions, and ‘Snippets’ for any extra chunks of JS that you might want to run to help debug things. The Snippets are available across any site you visit, and here’s a list of snippets if you’re interested in using them. I’ll skip the details of the ‘Content scripts’ too as dealing with chrome extensions deserves it’s own article. So, to the ‘Sources’ tab! Well, it’s pretty much exactly what it looks like – a file tree for what the browser has loaded for your site.

The file viewer / editor

This is another area that is pretty simple. We can un-minify code by clicking the curly braces in the bottom left and set breakpoints (in js files) by clicking the line numbers. The breakpoints also take conditions: right click on them and edit, which might be good for something like a loop in which you don’t want to break on every single iteration.

Within the file view we also have a few interesting options through the context menu (right click).

  • Add source map: If you’re running a pre-processor that minifies and concatenates your code into a single file, this tells the DevTools where the code came from. So, say you’re styling with Sass, when you inspect an element the styles that apply to it will show a link to the relevant sass files rather than the main.css file. The source maps will usually come from whatever pre-processor you’re using so we don’t have to worry about its implementation – it’s automatic!
  • Local modifications: shows the history of changes we’ve made to this file through the DevTools. This should open up in the drawer, although I’ve noticed that not every file will show it’s history.
  • Blackbox script: this stops the debugger from stepping into or pausing on exceptions within specified files (eg jquery). In the file tree, right click and select ‘blackbox’ or ‘unblackbox’. You can see a list of blackboxed files from the DevTools settings (the top right gear icon) -> sources -> Manage Framework Blackboxing.
  • Reveal in navigator: show this file in the file tree. When clicking a file link from one of the other panels, its location won’t be automatically popped open in the file tree – this is just a handy shortcut to do that.
  • Open link in new tab / copy link address: same as the browser link equivalents.
  • Save / save as: if you’ve made changes, save them on your local system – maybe even directly into your project! Also, press ctrl + s to save any live changes to the sites sources and see their effects on the page.

Debugging That panel on the right with a lot of drop downs.

Here we can control the execution and view meta data about the code we’re debugging. A side note on this subject: Paul Irish has a great 2 min demo of debugging a live site that shows this panel in action. But back to our run through: the top row here holds the usual controls for controlling execution:

  • pause / play: this will stop execution the next time any JavaScript runs. If we click and hold, a second play icon appears below it, this is the ‘long resume’ – selecting this will start the JS execution and ignore any breakpoints for 500ms.
  • Step over / in / out: the usual debugging controls
  • Toggle breakpoints: turn them on / off, easy!
  • Pause on exceptions: stop execution when an exception occurs. It can stop for both caught and uncaught exceptions when the checkbox is ticked, or just uncaught exceptions when it’s not.

Speaking of exceptions: window.onerror lets us override it with a function of our own to handle any unexpected exceptions that might bubble up. Any edge cases that testing might miss – this is pretty much our last chance to find them bar an angry customer.

window.onerror = function(message, url, line){
    //log to the console / send to server / send GA exception event.

Back to the layout! Below that bar of controls is a series of drop downs that hold many, many interesting things:

  • Watch Expressions: We can write in expressions here and watch them change while stepping through code, here’s a pretty good demo if you’re interested.
  • Call Stack: Starting at the current function, this works its way out listing the series of functions that were called to get to where we are currently paused (the execution path).
  • Scope Variables: These are specific to the line of JS that we’re paused on. It lists all the variables that are available from the local scope, up through the various calling function scopes to the global scope.
  • Breakpoints: lists the breakpoints we have set on line numbers – and lets us toggle them.
  • DOM Breakpoints: Remember these from the elements panel? Subtree modifications, Attributes Modifications, and Node Removal: they’re all listed here too.
  • XHR Breakpoints: We can break whenever any XHR communication happens, or press the + button to define a specific url. We don’t need the full url though – only a bit used to match against requests.
  • Event Listener Breakpoints: This gives us a list of events which we can toggle breakpoints on (I also find it handy as a concise & organized reference for what events we can play with).

Just a small note while we’re on the subject of breakpoints. We can write one directly into our code with debugger;. Whenever chrome comes across this, it will pause execution so we may begin debugging – good to know if you know where the code is in your editor and don’t fancy digging through it all in DevTools! Also, once the execution has paused on a function we can use the console in the drawer (press esc) to experiment within the current scope (like an interactive version of the Watch Expressions – or you could say Watch Expressions are like an automated console for debugging. Every angle you could think of seems to have been covered!)

Debugging dynamically loaded Javascript can be done too. If we add //# sourceURL=dynamicScript.js (the file name can be anything you want) the dynamic script will show up in the file tree under a file of your set name so that we can interact with the loaded script in the same way as we do with static script files.

Timeline client side performance

We’ve seen how the Network panel can analyse the speed of transferring resources, but that’s often only the first half of the battle. The timeline panel gives us the tools to dive into the performance of scripting, rendering, and painting (important for mobile devices with less power) as well as loading over the network for context. Here we see what’s going on in the browser once it has all the things our servers have sent it!

To get started, it’s similar to the network panel: click record, do an action (reload the page / interact with something that does something visually interesting), stop the recording. Again, it’s best to record short events (there’s even more data being generated here than in the Network panel!) and try to do it in incognito to avoid that extensions noise. Now that we have some data recorded, you should see it’s split into a few horizontal sections.

The controls in the top row: See a pattern forming? So far the Network, Sources and Timeline panels all have meta controls set along the top bar and each do fairly similar things:

  • Record: start / stop. Recordings will only be taken with DevTools open and the record options running. It’s probably not a good idea to have it running for long periods anyway – that would create an avalanche of data!
  • Clear: deletes the current recording.
  • Filter: for filtering the data we see, this also shows us the color coding for the 4 types (blue: loading, yellow: scripting, purple: rendering, and green: painting).
  • Collect Garbage: runs garbage collection.
  • Frames view: This shows us how long each frame takes to render: height is time, columns are frames. the horizontal lines show what we should be aiming to stay under in order to achieve their indicated frame rates. When both this and the records view are toggled, individual frames are indicated on the waterfall by vertical grey lines for a more intuitive view of the time frames take.
  • Events view: This isn’t one of the controls, it’s the view we have when the ‘Frames view’ is off (a kind of sneakily implied view) – three rows that show events over time (which is now on the ‘x-axis’), again with the color coding mentioned in the ‘Frames View’ description above.
  • Flame chart: This shows execution time (horizontal) and depth (height), we’ll get more into this in the next section (‘Profiles’), which also has a flame chart. One extra thing to note about the chart in this panel: we can scroll down to see the details of any extra threads that were running.
  • Timeline / Records view: Like the events view, this isn’t in the control bar – it’s just the view we have when the flame view isn’t on. It’s like the Network’s waterfall view sorted by start time, except this one shows all four of our event types.
  • Causes: I have to admit, this one I can’t figure out – If you have a good explanation, please share in the comments down below!
  • JS profiler: When checked (before recording) this will add Javascript call stacks to the flame chart. This is mainly for added context as profiling JavaScript is better done in the ‘Profiles’ panel.
  • Memory: shows the use of memory over time, this is the simple version. To get more into the gritty details, check out the next panel: ‘Profiles’ (again!).
  • Paint: If checked before recording, this allows us to drill into individual paint profiles. In the records list, click one of the paint events and (after processing for a little bit) we’ll see a timeline in the bottom details panel with every paint event and a small visual preview of what that paint event did – we can click and drag on that tiny timeline to see the paint progressing over time. Even more – by hovering over the paint command list down the left side, the relevant element on the page will be highlighted, and we can right click to find it in the elements pane. I hope that I’m not alone in thinking that this an absolutely astonishing level of detail! For most of the work we do on websites, this isn’t required – but if you’re into (or ever get into) some more immersive online experiences, I’m guessing this will turn out to be a really good tool.

First paint is also shown in the various time lines (the green line) as well as the DOMContent loaded (blue line) and load event (red).

CPU time is shown above the timelines as light grey horizontal bars. We can hover over these to see some extra details, but the main thing to note is the gaps between them. These are idle periods that explain any big gaps in the waterfall (as opposed to possibly thinking any rendering/painting is being blocked by something) – don’t go chasing any wild geese!

Profiles execution & memory performance

With the timeline panel we can see how long things are taking and what’s going on with the rendering/painting. But it’s not the most revealing when it comes to memory or what’s actually happening within our scripts. So we have the ‘Profiles’ panel to expose yet another deluge of data! Personally, I’m (currently) not that familiar with some of the specifics. Fortunately, the Google guys have put together a Memory Analysis 101 document which will make the contents of this panel more readable. When we open this panel (as of writing) we are presented with three choices. Every time we use one of these, the results are listed in the left hand column so we may perform these measurements several times and switch between them.Hopefully that makes sense as we’re going to jump into each individually:

Collect JavaScript CPU profile

This records the activity of our scripts. With it we can see which functions are taking up the most CPU time, and therefore which functions we should focus on when making performance improvements.

As before, keep your recording quick and clean to avoid an overwhelming amount of data. We can record several profiles and flick between them – they’re listed on the left under ‘CPU PROFILES’. For each recording we have three views:

  • (Flame) Chart: which we’ve seen in the Timeline panel – x is time, y is the call stack. Watch out for really wide bars – they’re the ones taking a while. We can also enable ‘High resolution CPU profiling’ in the settings to drill down to 1/10th of a second (if you want to).
  • Heavy (Bottom Up): a list of the functions sorted by running time.
  • Tree (Top Down): A nested list of the functions. This is another detail I haven’t’ fully worked out yet – explanatory comments would be appreciated!

For the last two items you’ll see some extra options along the top bar:

  • Focus selected: show only the selected function (& reset when you’ve focused in on one)
  • Exclude selected: just the opposite – remove the selected function from the list.

Take Heap Snapshot

If you suspect your app / site of having a memory leak (the effects of which can be seen in memory mode in the timeline panel), then this is the place to come and figure out the culprit. These are mainly for comparison between multiple snapshots rather than inspecting individuals as each one contains everything in the heap (which is a lot). Addy Osmani has a great workflow description for viewing memory leaks.

Every snapshot you take is listed on the left under ‘HEAP SNAPSHOTS’. Following the workflow mentioned, we’ll usually be dealing with a few snapshots. In the top bar (ignore the record/clear buttons) we have some options in a dropdown to help us inspect and compare snapshots:

  • Summary
    • All Objects – the details of everything in the selected snapshot
    • Objects allocated before snapshot 1 – This one I find strange, maybe I’m missing the point but surely objects allocated before the first snapshot and the objects listed in the first snapshot are identical? Let me know if you can – we’ve got a comment form at the end!
    • Objects allocated between snapshot n and snapshot n – this will show any memory leaks, all the objects that are hanging around between snapshots that shouldn’t be.
  • Comparison: between the selected snapshot and the one we specify in the second dropdown.
  • Containment: a ‘bird’s eye view’ of the object structure, lets us dive in to see everything at a very low level.
  • Statistics: simply showing us the breakdown of the snapshot.

Record Heap Allocations

This combines heap snapshots with the timeline – new object allocations are indicated by the vertical blue bars in the small timeline that appears. Each recording is listed on the left under ‘HEAP TIMELINES’. There’s not much more to add, the Docs (as of writing this) don’t cover this part – it’s pretty new!

Resources all the local storage

If your application stores anything client side, we want to see it. This panel gives us easy access to each way of storing things (except service workers, they get their own type of inspection, but that’s for another article.) It’s a pretty simple panel, almost the simplest. These are the various types of resources we can look into with it:

  • IndexedDB The modern way to store large amounts of data client side.
  • Web SQL Drilling into individual tables we will see their contents in the main panel, and if we click on the databases they’re within, we get a prompt for running SQL commands. Note, this spec is depreciated (since 2010), IndexedDB is the newer alternative.
  • Cookies These are organized in ‘frame groups’ (as in per domain). Right click to clear individual cookies or the whole lot from a single domain – note that cookies can be duplicated across domains, take heed if one seems to be particularly belligerent!
  • Application Cache This shows the files that have been saved (as per the app cache manifesto), but honestly – we should really be switching to Service Workers now.
  • Local / session storage Double click to add and edit, right click to delete. Refresh the page to see any impact (F5 I believe).
  • Resources (frames) All the files, scripts, content that has been downloaded by the page. If you have recorded the page load in the network panel then we can right click a resource and be redirected to the relevant place in the network panel. Although, if you’re looking through these things you’re probably better off in the Sources panel.

Audits recommendations for performance

Speed is good, required even, so any extra help in optimizing our sites (especially free and easy help) is amazing. Click run to see a list of suggestions color coded by severity – easy!

Console the console!

This is something we could not live (develop) without. We can log information to it from our code in a surprising number of ways and interact within various scopes, eg any iframes or chrome extensions (use the drop down in the top row to switch between them). This panel deserves its own article (like most of the things in the DevTools). Here I’ll just give a quick overview of some of the things we can log from our code. For more in depth reading, check out the console API and the command line API.

One extra note: in the dev tools settings we can set the console to “Log XMLHttpRequests”, if it’s not on already – turn it on! It’s great! Why isn’t this a default?

The Console API using the console from our code

Log types: These can be filtered (toggle the filter button in the top row, then choose your setting!)

console.log('','',''); //Multiple args!; //Prints an 'i' then the message
console.warn(); //Prints an '!' then the message
console.error("message"); //prints red and shows stack trace in a collapsed group
console.trace(); //prints a stack trace
console.assert(); //if first param is false, logs as error, else - logs normally
console.count("string"); //appends the number of times this exact string has been logged
console.table([{"col name":1, b:2, c:3}, {"col name":"foo", b:false, c:undefined}]); //try it!
console.clear(); //clears everything out the console

Log timing: these will also appear in the Timeline panel.
Note, time and timeEnd have to be passed the same string

//like a stopwatch
console.time("timer id string");
    function(){ ... }
    console.timeStamp("message/label"); //this has to be within a running timer
    function(){ ... }
console.timeEnd("timer id string");

Grouping logs: for organizing all the info we’re printing.

//Prints expanded"Group name");
    console.log("group log 1");
    console.log("group log 2");

//Prints collapsed
console.groupCollapsed("group name");
    console.log("group log 1");
    console.log("group log 2");

Emulation All the devices (almost)

Unless you have a collection of devices permanently hooked up to your development environment, this is going to save a lot of time. The emulation panel is a little hidden, it’s in the drawer (press esc while focused in the DevTools window). Once open you’ll have to toggle ‘Device Mode’ (unless it’s already on) – top left, at the start of the main list of panels. From here we can play with quite a few settings to help us emulate various devices which are mostly self explanatory, but I’ll run through them quickly:

  • Device: allows us to set screen size/resolution/pixel ratio, manually or through the list of presets.
  • Media: tick the checkbox to enable the drop down: look at all those things we can emulate!
  • Network: this is important when you’re looking at mobile users with limited network performance.
  • Sensors: Touch screen and geolocation should make sense just by their names. Accelerometer – this is the fun bit: tick the checkbox then click and drag the box image beside it, nice!

Media query inspector Up in the top left, in the dark border that should have appeared around your site when emulation turned on, you’ll see a small waterfall icon under the reset button. This magic little button was one of he things that had eluded me until writing this article – it gives us a visual representation of the various media queries that have been set in the site’s CSS. A great trick is to hit the reset button so we have our full desktop site visible, then click around the mediaquery waterfall, brilliant! We can also right click on them to reveal where they have been declared in the source code (in the Sources Panel), even more brilliant!

  • Top, blue bar: max width media queries
  • Middle, green bar: range width media queries
  • Bottom, orange bar: min width media queries

Note, emulation in the browser is not 100% accurate – you’ll still need to test in other browsers and devices.

Remote debugging Inspect element… on a phone!

For those moments when the site runs perfectly when emulating a device but breaks when running on the real thing, other than guessing – how do you figure out what the problem is?!? Well, if you’re running chrome on an android – just plug it in! You’ll have to set up your device for debugging, but once that’s up and running we can go to town on the site running on your phone.

  • Touch Inspect elements: click the search icon in DevTools. This will make touch events on the phone act as ‘right click / inspect element’.
  • Refresh from DevTools: F5
  • View cell network activity: in the network panel as usual! Just make sure the device isn’t hooked up to wifi.
  • Use the timeline panel: It’s particularly crucial with mobile devices.
  • Screen cast: show the phone’s screen, in DevTools, on your machine, and interact with it. That’s nuts.
  • Port Forwarding: will allow the device to pick up on any resources that may only be on your development server.
  • Virtual Host Mapping: This is for when we’ve configured virtual hosts, which the connected device will need to access; setup details are in the link!

For other devices and other browsers on those devices it would be great for remote debugging to work. Hopefully, future developments will bring an easy catch all solution for this. Also, for testing on a huge range of devices that we may not have acces to (going off the topic of DevTools a bit, I know), Open Device Lab looks to be a really good option. I’ve yet to use it, but maybe one day the opportunity will come round!

The End

Phew! If you’re interested in going deeper (that would amaze me as it means I’ve not dissuaded you already) you can always go through the docs too, or (the easy way) just look at gifs of everything. There is also a collection of short videos that go over the tools. It’s always good to see these things in action! I know I’ve gained more than a few insights from these resources and from putting this article together, I can only hope it’s done the same for you! Finally, for a bit of a curve ball, if you don’t like DevTools – you could always build your own, no joke! They’re written with HTML, CSS and JavaScript! That, I think, is just showing off.

« Prev Article
Next Article »