Open Chrome right-click on the screen to target inspect and click to open dev tools.
Click on the three dots and select dockside to set the dev tools orientation.
Console
Now let’s discuss more about console tabs
The console is a place to log messages generally. The browser also uses this place to log messages. This message could be a network request failure, a Javascript code syntax error, or a runtime error. So, the most common use case of the console is to dump information.
Types of consoles
We can make use of different kinds of consoles to
Making buttons for firing different consoles at click events.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<main class="ctas-container">
<button class="cta cta-info" onClick="logSomething('INFO')">Log Info</button>
<button class="cta cta-warn" onClick="logSomething('WARN')">Log warning</button>
<button class="cta cta-error" onClick="logSomething('ERROR')">Log error</button>
<button class="cta cta-table" onClick="logSomething('TABLE')">Log table</button>
<button class="cta cta-group" onClick="logSomething('GROUP')">Log group</button>
<button class="cta cta-custom" onClick="logSomething('CUSTOM')">Log custom</button>
<button class="cta cta-error-404" onClick="logSomething('ERROR-404')">Log error 404</button>
<button class="cta cta-violation" onClick="logSomething('VIOLATION')">Log violation</button>
</main>
</body>
</html>
We will style these buttons
* {
font-size: 62.5%;
}
.ctas-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px 20px;
}
.cta {
padding: 5px 7px;
font-size: 1.3rem;
line-height: 2rem;
color: #fff;
background: linear-gradient(to right, #ec2323, #3b2be5);
border: 1px solid #4c49491a;
cursor: pointer;
}
Now we will write a script to see how different consoles work and where we can use them for debugging.
const logSomething = (logType) => {
switch (logType) {
case "INFO":
console.log("Hello normal");
break;
case "WARN":
console.warn("Hello warning");
break;
case "ERROR":
console.error("Hello error");
break;
case "TABLE":
console.table([
{
first: "Dev",
last: "Rana",
},
{
first: "Mrunal",
last: "Sita",
},
]);
break;
case "GROUP":
const label = "Adolescent Hey";
console.group(label);
console.info("Leo");
console.info("Mike");
console.groupEnd(label);
break;
case "CUSTOM":
const spacing = "5px";
const styles = `padding:${spacing};background-color:darkblue;color:white;font-style:italic;border:${spacing} solid crimson;font-size:2em;`;
console.log("%cEternal soul.", styles);
break;
case "ERROR-404":
fetch("https://abckuchbhi.com");
break;
case "VIOLATION":
console.debug("Hello verbose error!");
const duration = 3000;
const start = new Date().getTime();
while (new Date().getTime() < start + duration) {
// block the main thread for 3 seconds
}
break;
default:
console.warn("Select valid log option!");
}
};
We will have the output as follows
I will explain each kind of console in detail and their use cases.
Log info
console.log - outputs whatever is written inside it.
Log warning
console.warn - outputs whatever is written inside it and a warning sign.
you can also observe hyperlinks at the right end ofthe above screenshot. By clicking on it, you can identify which js code is causing that warning log by navigating to that line inside the source tab.
Log error
console.error - outputs whatever is written inside it and an error sign.
We have other special utility-based consoles that are not used that much often.
Log table
You may generally use it if you are a plugin or library developer trying to debug a plugin.
console.table - outputs a table for an array of objects as input.
Log group
You use console.group, console.info, and console.groupEnd to group logs under a label.
Log custom
We can make custom-styled logs as follows.
Cause error
Give stack trace error.
We can see how we get stack trace along with error. The above ss says the error occurred due to logSomething which was fired due to the onClick event.
Cause violation
It generally logs in the verbose section.
We can use console.debug to log them or write a thread-blocking code.
As we can see we get both kind of logs(violation and debug) under verbose section.
Console search
You can use console search to filter out your console logs. You can search based on string or text or you can use RegEx - which is a more mathematical way of matching expressions in a text. RegEx is also extensively used to write input validations of forms or rewrite rules in .net.
Syntax - / string pattern / - anything written inside it is considered RegEx by console search.
Source tab 101
In the source tab, we can see three general sections.
In the first section, we can see different tabs like Page, Workspace etc.
Onthe Page tab, we can see files in a file structure with the top as root. We have origins of particular assets being loaded inside it. Any website may not just be using its resources like ones inside code, logos etc. but there can be external resources like font-family etc.
We can see anything and everything a site has loaded from here either through network calls or extensions being used.
The source tab has various tabs.
Pages tab - Gives us a list of pages/resources/assets being loaded.
Filesystems tab - Used to edit our code within dev tools by importing our code repo from the local system and editing files directly in it will also change that file locally.
Overrides - Sometimes you need to try out some possible fixes for a webpage, but you don't have access to the source files, or changing the page requires a slow and complex build process. You can debug and fix all kinds of problems in DevTools. But the changes don't persist; all your work is gone after you refresh the local file. The Overrides feature in the sources tool helps you solve this problem.
You can now take a resource from the current webpage and store it locally. When you refresh the webpage, the browser doesn't load the resource from the server; instead, the browser replaces the server resource with your local copy.
Content scripts - They are generally a list of all Chrome extensions.
If we want to make a Chrome extension mess with our actual page we can debug our content scripts here.
Snippets - It is a little feature which can come in handy when say you are executing the same script over and over again on a particular page like the automation script which we have not installed in our system.
Setting up debugger
Inside Pages tab - when we select the rendered page HTML document it gives us raw HTML which looks similar to the one shown in the elements tab but there is a big difference.
One in the elements tab is not an HTML document but a DOM representation.
But one inside Sources > pages > HTML file is a raw HTML document sent in a response to our request.
Inside js code, we can pause the execution of our code using breakpoints.
In js code wherever we add breakpoint a blue color highlights that line.
Nothing can be executed after this breakpoint until we want to.
Js world has come to pause and js execution has come to pause.
In this state, we can modify other lines of JS code so that when we resume our JS code execution we can debug and get some results which may help in debugging.
We have added debuggers by going to the source file and adding it manually. We can also add conditions to that breakpoint as below.
Conditional debugger
We can add conditional breakpoints by right-clicking on any breakpoint and adding a valid conditional expression.
Another way of adding a breakpoint is by adding a debugger in our code.
Event-based debugger
In the sources tab below call stack and breakpoints we have XHR/fetch Breakpoints where we can add conditions like below or you can click the + icon without adding any condition and break for any XHR request.
DOM breakpoints
Go to the elements tab, right-click on any element, and hover on the Select break on option - subtree modifications, attribute modifications, node removal.
Subtree modifications. Triggered when a child of the currently selected node is removed or added, or the contents of a child are changed and not triggered on child node attribute changes or changes to the currently selected node.
Attributes modifications: Triggered when an attribute is added or removed on the currently selected node, or when an attribute value changes.
Node Removal: Triggered when the currently selected node is removed
Event listeners breakpoints
Go to the mouse section and click the event checkbox. This will pause execution on any click event in the DOM. Similarly, you can see other events. These event breakpoints allow us to debug how various extensions behave on these events on our page and see their underlying logic. It is not recommended and try to use it to reverse engineer some websites whose prod code is unavailable to you.
Stepping in debugger
How can we step in and out of functions in a debugger call?
const logSomething = () => {
const a = 100;
b();
};
const b = () => {
const c = 150;
d();
};
const d = () => {
const e = 200;
f();
};
const f = () => {
console.log("Done!;");
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<main class="ctas-container">
<button class="cta" onClick="logSomething()">Call Starting</button>
<button class="cta" onClick="b()">Call b()</button>
<button class="cta" onClick="f()">Call f()</button>
</main>
</body>
</html>
* {
font-size: 62.5%;
}
.ctas-container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px 20px;
}
.cta {
padding: 5px 7px;
font-size: 1.3rem;
line-height: 2rem;
color: #fff;
background: linear-gradient(to right, #ec2323, #3b2be5);
border: 1px solid #4c49491a;
cursor: pointer;
}
We can Instead of analyzing the state at the single point of debugging, we can move forward in time step by step.
We will first click on Call Starting cta.
In debug mode, we can move forward by clicking onthe Step over next function call button which will push us to the next function call.
The highlighted line is always the one being executed in js code in debug mode.
Clicking on Step over next function call button moves to the next line.
Js will always move to the next line sequentially.
Now on clicking on the Step over next function call button again, it will close the execution of function logSomething() and b() are called inthe background and then the rest of the code of this function is executed in the background and missed if we want to debug this function code line by line.
So to prevent such a situation what we can do is when the b() invoked line is highlighted we would click on the Step into next function call button which makes us step into the next function call and we won’t miss these steps again.
Breakpoints
function f() {
console.log("Done!;");
if (Math.random() > 0.5) {
// crash the code
throw new Error("Well the luck is not with us!");
}
}
f();
For the above type of code sometimes we will get an error like below.
And most of the time not as below.
So, how do we set a debugger?
By adding a breakpoint on throw new Error line.
But it is not feasible to add manually for the huge code base.
So, we enable pause in the uncaught exception mode as shown below.
It means that whenever js is about to throw an exception, it will break the js code execution. It allows you to analyse the situation where the exception occurs and handle your logic accordingly.
Note - By default, it does not handle uncaught exceptions which are written insidethe try block.
function f() {
console.log("Done!;");
if (Math.random() > 0.5) {
// crash the code
try {
throw new Error("Well the luck is not with us!");
} catch (error) {
console.log("Prevented an oopsie!");
}
}
}
f();
In the above case, Pause on uncaught exceptions will not work.
We need to enable pause on caught exceptions mode to break the js execution when error occurs.
By clicking the deactivate breakpoints button highlighted on the right of the devtool screenshot above, we can disable all breakpoints together instead of doing it manually.
Call stack
It is a data structure that helps you to maintain the execution of functions—the order in which the functions are executed.
const logSomething = () => {
const a = 100;
b();
};
const b = () => {
const c = 150;
d();
};
const d = () => {
const e = 200;
f();
};
const f = () => {
console.log("Done!;");
};
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<main class="ctas-container">
<button class="cta" onClick="logSomething()">Call Starting</button>
<button class="cta" onClick="b()">Call b()</button>
<button class="cta" onClick="f()">Call f()</button>
</main>
</body>
</html>
In the above example, f is called by d which is called by b which is called by logSomething which is called by the onClick event attached to the Call Starting button.
It will always be a linear execution.
One-click may lead to calling more than one function but you’re not seeing the call stack of that particular function.
Because a single event say click at a time can call onlya single function because js is single-threaded.
Whenever we stop the execution of the single thread we will always get a linear call stack.
Patch code on runtime
In sources tab when we directly update our code it does not automatically reload our js page but it saves that code on run time temporarily so, if there is a code which does not run only on page load like below we can see the result of our modified code.
setInterval(() => {
consoleLogSomething();
}, 1000);
function consoleLogSomething() {
console.log("something not funny!");//we can modify this text on source code and see the result
}
Snippets
It is a way to execute a certain block of code almost immediately.
A real world use case can say we have AWS S3 storage.
We want individual files of the uploaded folder in S3. We can create a snippet that extracts all that information from the DOM; I only need that for that particular domain.
Another use case can be to make documents editable.
We can create a a new snippet, write some code, save it as shown in the screenshot above, press ctrl+enter, or click the the play button below to see our code result.
We can use snippets to write code extracting data from our website.
We can also open multiple links by writing a simple JS code to loop an array of links and redirect/open a new page using the target blank attribute by creating an anchor element using JS.
We can click ctrl+p to list snippet files and select one to execute it.
Network Tab
Q. Why Chrome only log when we open Dev tools?
A. To reduce CPU and resource consumption due to logging. Not many are developers out there who uses Chrome.
You can disable show overview in the network tab which shows latency, and request time as a frontend developer.
It generally depends on the DNS time, request time, response time etc. which we can’t do much about.
We can use a red dot to pause and enable network logging.
In the network tab, the requests are laid down in the order they are made not in the order they are resolved.
Each request has various information.
In the headers tab, we can see one of that info related to a particular network call.
The general section contains basic info about the request made.
Response headers are the headers which are sent by the remote server.
Request headers the headers which we make.
Preview Tab - HTML preview of the response from server.
Response Tab - This is the raw interpretation of what you have from the server. Preview is like a document of the page but the response is the HTML response.
We can pretty print the content of the response by clicking on the {} button at the bottom.
Initiator tab - gives us a chain of requests,and how it happened. From top to bottom, it tells us what we requested and how that request led to other requests being made down that list.
Timing tab - essential to do optimization. TTFB - Time to first byte shows how long the browser waits for the server to respond.
Cookies tab - It displays the list of cookies set on this particular page due to requests we make.
Filters -
XHR - Ajax or fetch request list
JS -
All js files are being loaded.
CSS -
All CSS files are being loaded.
img -
All image files being loaded.
media -
All video/audio files are being loaded.
font -
All font apis are being called.
Doc -
Our whole website doc or iframes or other docs are called using fetch or other methods.
WS (Web Sockets) -
For relative use, network call list. Such as online code editors, chat web apps, etc. where sockets are required and used.
Manifest (manifest.json) -
We can see the loaded manifest.json file.
Others -
We can see files that do not fall under other categories.
Columns in network tab -
We can right-click on the column name and check things we need to be seen like request name, status, type etc.
Connection ID tells us what TCP connection is carrying out that request.
Throttling -
Slow 3G, none, etc. can be used to reduce the loading speed of your webpage.
It generally does not work with web socket connections.
Copy request payload
Right-click on any network call request.
You can hover on copy and get multiple copy options like copy as fetch etc.
Elements Tab
Source code vs Inspect HTML element
The server sends us the raw HTML document, the raw contents, HTML head, title, meta, metadata, script, etc.
Even if raw HTML is broken or some things work out to be fine.
Inside the elements tab, we have an actual representation of the HTML DOM (DOCUMENT OBJECT MODEL) tree.
It is always the perfect HTML. Our browser has fixed our broken HTML and tried to make a lot of sense of what we are writing and it has done all the good stuff.
No matter in out HTML document we have just written, <h1>Heading</h1>
Our browser DOM tree i.e. element tab has magically constructed valid and proper HTML elements like <html>, <head>, <body>, etc. which is not visible in our source code.
Inspecting a node
you can use color picker by clicking on color code square as below.
You can use eye dropper from color picker to get hex code of any element in a page as below.
li, p, etc. is a node
You can right click and inspect element or use picker to target element in elements tab top left.
We can search nodes inside elements tab by clicking ctrl+f as below
Operations with a node
In elements tab DOM tree, we can edit elements or values.
We can drag and drop elements by clicking and holding three dots and dragging it.
Special variable ($0)
Whenever we select an element inside elements tab DOM tree, a $0 symbol appears beside it which we can see when we hover it.
We can use it in the console tab as $0.
$0 directly prints the selected node element of elements tab DOM tree.
$0 only for debugging, not use in actual code.
$0.innerText gets text of selected html DOM tree element.
Manipulate styles
We can select the DOM tree element and on right side styles tab we can manipulate our element styles.
We can also find user agent stylesheet which can’t be edited as it comes from the browser engine itself and is not present in the page.
We can toggle element states by clicking on .hov option for hover state.
We can use .cls to make a selector for selected DOM tree element.
Copying CSS path
Right click on DOM element.
hover on copy
select copy selector
This will give accurate selector for that DOM element
Similarly we can also copy JS path which automatically makes queryselector script for that element.
Color picker
We can use color picker magnifier to get hex code value of anything appearing in our web page as discussed above.
We can also see the contrast information when we hover on element color and get contrast information.
Contrast ratio increases accessibility and readability.
We can also toggle to other values for color other than hex using color picker.
Thanks for reading.
Happy debugging.