You can add DOM breakpoints to help understand what is going on.
You can save changes to disk! You can add folders to the workspace and it will try map files being served to those from your folder. Styles can persist, DOM will not.
Cool tibit - Cmd + Shift + P opens a command input, while in sources cmd + P opens a search to go through your files.
Debugging
Step Through Debugging
In the example, the debugger keyword is inserted into a file under the Sources tab that can be used to force a breakpoint.
When a break point is triggered, it shows you the current Call Stack, Scope and more.
There are navigation options for stepping over things.
Debugging Section
Does
Watch
Shows the variables you are watching in real time.
Call Stack
Shows the JS call stack for how you got there.
Scope
Shows all vars in scope (including global).
Breakpoints
Lists all breakpoints you have.
XHR/fetch Breakpoints
This can stop when a URL set is called to.
DOM Breakpoints
Adding breakpoints based on the DOM.
Global Listeners
TODO
Event Listener Breakpoints
Adding breakpoints based on events.
How the Debugger stepping works:
Option
Does
Continue
Resume script execution.
Step over
Stepping through code.
Step into
Move into the function the BP is on.
Step out of
Move BP back to parent that called step into.
Step
A single step. Over or into if it is a func.
You can also blackbox a script to ensure things do not show in the Call Stack debugger.
In the example run, we are adding variables to the watch value in source and watching them change.
Networking
This is a general overview of the status, type, initiator, size etc.
There are also filters to check file type, XHR request etc.
Hold the shift key will show you which file called it. Initiators are green, while dependencies are red. See the network reference.
Network Timing
Information
Does
Queueing
The browser queued the request.
Stalled
The request could be stalled for any of the reasons described in Queueing.
DNS Lookup
The browser is resolving the request's IP address.
Proxy negotiation
The browser is negotiating the request with a proxy server.
Request sent
The request is being sent.
ServiceWorker Preparation
The browser is starting up the service worker.
Request to ServiceWorker
The request is being sent to the service worker.
Waiting (TTFB)
The browser is waiting for the first byte of a response.
Content Download
The browser is receiving the response.
Receiving Push
The browser is receiving data for this response via HTTP/2 Server Push.
Reading Push
The browser is reading the local data previously received.
TTFB stands for Time To First Byte. This timing includes 1 round trip of latency and the time the server took to prepare the response.
Queueing
A request being queued indicates:
The req was postponed by the rendering engine beacuse it's considered lower priority than critical resources (ie scripts, styles). Often happens with images.
The req was put on hold to wait for an unavailable TCP sockets that's about to free up.
Req put on hold because the browser only allows six TCP connections per origin on HTTP 1.
Time spent making disk cache entries (typically very quick).
Screenshots
You can enable capture screenshots (using the "camera" icon on the Network tab) which will show all the repaints as they happen.
You can also use filters in the search input ie larger-than: 100kb to filter out certain network requests.
Auditing
Begins with importance on speed decrease and adverse affect to large companies.
function usePerformanceEntryMethods() {
log('PerformanceEntry tests ...');
if (performance.mark === undefined) {
log('... performance.mark Not supported');
return;
}
// Create some performance entries via the mark() method
performance.mark('Begin');
doWork(50000);
performance.mark('End');
performance.mark('Begin');
doWork(100000);
performance.mark('End');
doWork(200000);
performance.mark('End');
// Use getEntries() to iterate through the each entry
var p = performance.getEntries();
for (var i = 0; i < p.length; i++) {
log('Entry[' + i + ']');
checkPerformanceEntry(p[i]);
}
// Use getEntries(name, entryType) to get specific entries
p = performance.getEntries({ name: 'Begin', entryType: 'mark' });
for (var i = 0; i < p.length; i++) {
log('Begin[' + i + ']');
checkPerformanceEntry(p[i]);
}
// Use getEntriesByType() to get all "mark" entries
p = performance.getEntriesByType('mark');
for (var i = 0; i < p.length; i++) {
log(
'Mark only entry[' +
i +
']: name = ' +
p[i].name +
'; startTime = ' +
p[i].startTime +
'; duration = ' +
p[i].duration,
);
}
// Use getEntriesByName() to get all "mark" entries named "Begin"
p = performance.getEntriesByName('Begin', 'mark');
for (var i = 0; i < p.length; i++) {
log(
'Mark and Begin entry[' +
i +
']: name = ' +
p[i].name +
'; startTime = ' +
p[i].startTime +
'; duration = ' +
p[i].duration,
);
}
}
Image Performance
We can use <img srcset="large.jpg 800w, small.jpg 300w" src="large.jpg" /> to use source sets for images.
The example used is using via.placholder.com to show how the different srcset works.
For a srcset, it will continue to fetch the bigger images as the media queries will hit as a screen gets bigger but not the other way. The thought is that network reqs are expensive but repainting is not so bad.
"Jumping" or "gittering" is consider page jank. Things that contribute this include layout thrashing.
The 60fps aim is because most monitors are 60 hertz. That's an update ~16.66ms. We basically want all of our work to happen at 10ms to give the update to the screen.
A geat website to test paint flashing from the Chrome Dev Tools is Koalas to the max.
We can turn off screenshots and memory to show less tabs.
What we have left over is the FPS, CPU and Network graphs on one panel and a breakdown of them all in the bottom panel.
For FPS, the higher the green line the better. As it uses a lot, it will start with a red bar across the top.
CPU will show a mix between rendering, painting, JS work.
The second panel full of call graphs is a breakdown of what is happening. The main thread is where we can see what is happening. Tall is not so bad (just means a large call stack), wide is where we get concerned. Again, there are red boxes that can help us.
When you select a box, it will show it below in the summary.
Once you profile and go to sources, it will give you timing out of the box on the side panel!
Memory
Common causes of memory leaks:
Accidental Global
function foo() {
bar = 'This is probably not what you mean';
}
// this reference needs to be removed
const button = document.getElementById('button');
function removeButton() {
document.body.removeChild(document.getElementById('button'));
}
Chrome Task Manager & Snapshots
You can use the task maanger and option + click and add JavaScript Memory.
Performance tab good for spotting a leak, memory for debugging.
The saw wave indicates a leak. It will also break that line down into different memory issues.
We can use the heap snapshot as an entry to start checking where things are happening through samples.
After recording, you can then use the filters to order things like shallow size, retained size etc. If this doesn't give you a good idea, you can take another snapshot and compared.
There is a website here that you can use to practice snapshots for memory leaks!
Memory snapshots do not map directly to the source code, but you can dig into where the issues are coming from in the panel to identify the source.
Experiments
To check experimental code, if you go to chrome://flags and turn on the experimental flag, you can then go to settings and turn on experiments.
Hitting shift seven times will reveal hidden experiments.