Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

⚡️ 💾 Web Performance Snippets

License

NotificationsYou must be signed in to change notification settings

tunetheweb/webperf-snippets

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

75 Commits
 
 
 
 
 
 

Repository files navigation

A curated list of snippets to get Web Performance metrics to use in the browser console

Core Web Vitals

Largest Contentful Paint (LCP)

/** * PerformanceObserver */constpo=newPerformanceObserver((list)=>{letentries=list.getEntries();entries=dedupe(entries,"startTime");/**   * Print all entries of LCP   */entries.forEach((item,i)=>{console.dir(item);console.log(`${i+1} current LCP item :${item.element}:${item.startTime}`);/**     * Highlight LCP elements on the page     */item.element ?(item.element.style="border: 5px dotted blue;") :"";});/**   * LCP is the lastEntry in getEntries Array   */constlastEntry=entries[entries.length-1];/**   * Print final LCP   */console.log(`LCP is:${lastEntry.startTime}`);});/** * Start observing for largest-contentful-paint * buffered true getEntries prior to this script execution */po.observe({type:"largest-contentful-paint",buffered:true});functiondedupe(arr,key){return[...newMap(arr.map((item)=>[item[key],item])).values()];}

Largest Contentful Paint Sub-Parts (LCP)

This script it's part of theWeb Vitals Chrome Extension and appear on theOptimize Largest Contentful Paint post.

Largest Contentful Paint Sub-Parts
constLCP_SUB_PARTS=['Time to first byte','Resource load delay','Resource load time','Element render delay',];newPerformanceObserver((list)=>{constlcpEntry=list.getEntries().at(-1);constnavEntry=performance.getEntriesByType('navigation')[0];constlcpResEntry=performance.getEntriesByType('resource').filter((e)=>e.name===lcpEntry.url)[0];constttfb=navEntry.responseStart;constlcpRequestStart=Math.max(ttfb,lcpResEntry ?lcpResEntry.requestStart||lcpResEntry.startTime :0);constlcpResponseEnd=Math.max(lcpRequestStart,lcpResEntry ?lcpResEntry.responseEnd :0);constlcpRenderTime=Math.max(lcpResponseEnd,lcpEntry ?lcpEntry.startTime :0);LCP_SUB_PARTS.forEach((part)=>performance.clearMeasures(part));constlcpSubPartMeasures=[performance.measure(LCP_SUB_PARTS[0],{start:0,end:ttfb,}),performance.measure(LCP_SUB_PARTS[1],{start:ttfb,end:lcpRequestStart,}),performance.measure(LCP_SUB_PARTS[2],{start:lcpRequestStart,end:lcpResponseEnd,}),performance.measure(LCP_SUB_PARTS[3],{start:lcpResponseEnd,end:lcpRenderTime,}),];// Log helpful debug information to the console.console.log('LCP value: ',lcpRenderTime);console.log('LCP element: ',lcpEntry.element,lcpEntry?.url);console.table(lcpSubPartMeasures.map((measure)=>({'LCP sub-part':measure.name,'Time (ms)':measure.duration,'% of LCP':`${Math.round((1000*measure.duration)/lcpRenderTime)/10}%`,})));}).observe({type:'largest-contentful-paint',buffered:true});

Quick BPP (image entropy) check

Context:Largest Contentful Paint change in Chrome 112 to ignore low-entropy images

This snippet is based on and with the permissionStoyan Stefanov, read his posthere.

With the script you can get a list of the BPP of all(1) images loaded on the site.

(1) the images with source "data:image" and third-party images are ignored.

console.table([...document.images].filter((img)=>img.currentSrc!=""&&!img.currentSrc.includes("data:image")).map((img)=>[img.currentSrc,(performance.getEntriesByName(img.currentSrc)[0]?.encodedBodySize*8)/(img.width*img.height),]).filter((img)=>img[1]!==0));

Cumulative Layout Shift

try{letcumulativeLayoutShiftScore=0;constobserver=newPerformanceObserver((list)=>{for(constentryoflist.getEntries()){if(!entry.hadRecentInput){cumulativeLayoutShiftScore+=entry.value;}}});observer.observe({type:"layout-shift",buffered:true});document.addEventListener("visibilitychange",()=>{if(document.visibilityState==="hidden"){observer.takeRecords();observer.disconnect();console.log(`CLS:${cumulativeLayoutShiftScore}`);}});}catch(e){console.error(`Browser doesn't support this API`);}

Loading

Time To First Byte

Measure the time to first byte, from the document

newPerformanceObserver((entryList)=>{const[pageNav]=entryList.getEntriesByType("navigation");console.log(`TTFB (ms):${pageNav.responseStart}`);}).observe({type:"navigation",buffered:true,});

Measure the time to first byte of all the resources loaded

newPerformanceObserver((entryList)=>{constentries=entryList.getEntries();constresourcesLoaded=[...entries].map((entry)=>{letobj={};// Some resources may have a responseStart value of 0, due// to the resource being cached, or a cross-origin resource// being served without a Timing-Allow-Origin header set.if(entry.responseStart>0){obj={"TTFB (ms)":entry.responseStart,Resource:entry.name,};}returnobj;});console.table(resourcesLoaded);}).observe({type:"resource",buffered:true,});

Scripts Loading

List all the<scripts> in the DOM and show a table to see if are loadedasync and/ordefer

constscripts=document.querySelectorAll("script[src]");constscriptsLoading=[...scripts].map((obj)=>{letnewObj={};newObj={src:obj.src,async:obj.async,defer:obj.defer,"render blocking":obj.async||obj.defer ?"" :"🟥",};returnnewObj;});console.table(scriptsLoading);

Resources hints

Check is the page has resources hints

constrels=["preload","prefetch","preconnect","dns-prefetch","preconnect dns-prefetch","prerender","modulepreload",];rels.forEach((element)=>{constlinkElements=document.querySelectorAll(`link[rel="${element}"]`);constdot=linkElements.length>0 ?"🟩" :"🟥";console.log(`${dot}${element}`);linkElements.forEach((el)=>console.log(el));});

Find Above The Fold Lazy Loaded Images

List all images that haveloading="lazy" or[data-src](lazy loading via JS) above the fold

functionfindATFLazyLoadedImages(){constlazy=document.querySelectorAll('[loading="lazy"], [data-src]');letlazyImages=[];lazy.forEach((tag)=>{constposition=parseInt(tag.getBoundingClientRect().top);if(position<window.innerHeight&&position!==0){lazyImages=[...lazyImages,tag];}});returnlazyImages.length>0 ?lazyImages :false;}console.log(findATFLazyLoadedImages());

Find non Lazy Loaded Images outside of the viewport

List all images that don't haveloading="lazy" or[data-src](lazy loading via JS) and are not in the viewport when the page loads. This script will help you find candidates for lazy loading.

// Execute it after the page has loaded without any user interaction (Scroll, click, etc)functionfindImgCanidatesForLazyLoading(){letnotLazyImages=document.querySelectorAll('img:not([data-src]):not([loading="lazy"])');returnArray.from(notLazyImages).filter((tag)=>!isInViewport(tag));}functionisInViewport(tag){letrect=tag.getBoundingClientRect();return(rect.bottom>=0&&rect.right>=0&&rect.top<=(window.innerHeight||document.documentElement.clientHeight)&&rect.left<=(window.innerWidth||document.documentElement.clientWidth));}console.log("Consider lazyloading the following images: ",findImgCanidatesForLazyLoading());

Find render-blocking resources

List all resources that are blocking rendering.

It's currently Chromium only

functionRenderBlocking({startTime, duration, responseEnd, name, initiatorType}){this.startTime=startTimethis.duration=durationthis.responseEnd=responseEndthis.name=namethis.initiatorType=initiatorType}functionfindRenderBlockingResources(){returnwindow.performance.getEntriesByType('resource').filter(({renderBlockingStatus})=>renderBlockingStatus==='blocking').map(({startTime, duration, responseEnd, name, initiatorType})=>newRenderBlocking({startTime, duration, responseEnd, name, initiatorType}));}console.table(findRenderBlockingResources())

Image Info

List all image resources and sort by (name, transferSize, encodedBodySize, decodedBodySize, initiatorType)

More Info

functiongetImgs(sortBy){constimgs=[];constresourceListEntries=performance.getEntriesByType("resource");resourceListEntries.forEach(({      name,      transferSize,      encodedBodySize,      decodedBodySize,      initiatorType,})=>{if(initiatorType=="img"){imgs.push({          name,          transferSize,          decodedBodySize,          encodedBodySize,});}});constimgList=imgs.sort((a,b)=>{returnb[sortBy]-a[sortBy];});returnimgList;}console.table(getImgs("encodedBodySize"));

Fonts Preloaded, Loaded, and Used Above The Fold

List all the fonts preloaded via resources hints, all the fonts loaded via CSS, and all the fonts used in the viewport above the fold.

constlinkElements=document.querySelectorAll(`link[rel="preload"]`);constarrayLinks=Array.from(linkElements);constpreloadedFonts=arrayLinks.filter((link)=>link.as==="font");console.log("Fonts Preloaded via Resources Hints");preloadedFonts.forEach((font)=>console.log(`▸${font.href}`));console.log("");constloadedFonts=[  ...newSet(Array.from(document.fonts.values()).map((font)=>font).filter((font)=>font.status==="loaded").map((font)=>`${font.family} -${font.weight} -${font.style}`)),];console.log("Fonts and Weights Loaded in the Document");loadedFonts.forEach((font)=>console.log(`▸${font}`));console.log("");constchildrenSlector="body * > *:not(script):not(style):not(link):not(source)";constaboveFoldElements=Array.from(document.querySelectorAll(childrenSlector)).filter((elm)=>{constrect=elm.getBoundingClientRect();return(rect.top>=0&&rect.left>=0&&rect.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&rect.right<=(window.innerWidth||document.documentElement.clientWidth));});constusedFonts=Array.from(newSet([...aboveFoldElements].map((e)=>`${getComputedStyle(e).fontFamily} |${getComputedStyle(e).fontWeight} |${getComputedStyle(e).fontStyle}`)));console.log("Fonts and Weights Used Above the Fold");usedFonts.forEach((font)=>console.log(`▸${font}`));

First And Third Party Script Info

List all scripts using PerformanceResourceTiming API and separating them by first and third party

More Info

Info On CORS

// ex: katespade.com - list firsty party subdomains in HOSTS arrayconstHOSTS=["assets.katespade.com"];functiongetScriptInfo(){constresourceListEntries=performance.getEntriesByType("resource");// set for first party scriptsconstfirst=[];// set for third party scriptsconstthird=[];resourceListEntries.forEach((resource)=>{// check for initiator typeconstvalue="initiatorType"inresource;if(value){if(resource.initiatorType==="script"){const{ host}=newURL(resource.name);// check if resource url host matches location.host = first party scriptif(host===location.host||HOSTS.includes(host)){constjson=resource.toJSON();first.push({ ...json,type:"First Party"});}else{// add to third party scriptconstjson=resource.toJSON();third.push({ ...json,type:"Third Party"});}}}});constscripts={firstParty:[{name:"no data"}],thirdParty:[{name:"no data"}],};if(first.length){scripts.firstParty=first;}if(third.length){scripts.thirdParty=third;}returnscripts;}const{ firstParty, thirdParty}=getScriptInfo();console.groupCollapsed("FIRST PARTY SCRIPTS");console.table(firstParty);console.groupEnd();console.groupCollapsed("THIRD PARTY SCRIPTS");console.table(thirdParty);console.groupEnd();/*Choose which properties to displayhttps://developer.mozilla.org/en-US/docs/Web/API/console/tableconsole.groupCollapsed("FIRST PARTY SCRIPTS");console.table(firstParty, ["name", "nextHopProtocol"]);console.groupEnd();console.groupCollapsed("THIRD PARTY SCRIPTS", ["name", "nextHopProtocol"]);console.table(thirdParty);console.groupEnd();*/

First And Third Party Script Timings

This relies on the above script

Run First And Third Party Script Info in the console first, then run this

Calculate Load Times - MDN

Info on CORS (why some values are 0)

Note: The properties which are returned as 0 by default when loading a resource from a domain other than the one of the web page itself: redirectStart, redirectEnd, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, and responseStart.


More Info on TAO header - Akamai Developer Resources

functioncreateUniqueLists(firstParty,thirdParty){functiongetUniqueListBy(arr,key){return[...newMap(arr.map((item)=>[item[key],item])).values()];}constfirstPartyList=getUniqueListBy(firstParty,["name"]);constthirdPartyList=getUniqueListBy(thirdParty,["name"]);return{ firstPartyList, thirdPartyList};}const{ firstPartyList, thirdPartyList}=createUniqueLists(firstParty,thirdParty);functioncalculateTimings(party,type){constpartyChoice=party==="first" ?firstParty :thirdParty;consttimingChoices={DNS_TIME:["domainLookupEnd","domainLookupStart"],TCP_HANDSHAKE:["connectEnd","connectStart"],RESPONSE_TIME:["responseEnd","responseStart"],SECURE_CONNECTION_TIME:["connectEnd","secureConnectionStart",0],FETCH_UNTIL_RESPONSE:["responseEnd","fetchStart",0],REQ_START_UNTIL_RES_END:["responseEnd","requestStart",0],START_UNTIL_RES_END:["responseEnd","startTime",0],REDIRECT_TIME:["redirectEnd","redirectStart"],};functionhandleChoices(timingEnd,timingStart,num){if(!num){returntimingEnd-timingStart;}if(timingStart>0){returntimingEnd-timingStart;}return0;}consttimings=partyChoice.map((script)=>{const[timingEnd,timingStart,num]=timingChoices[type];constendValue=script[timingEnd];conststartValue=script[timingStart];return{name:script.name,[type]:handleChoices(endValue,startValue,num),};});returntimings;}// Available OptionsconsttimingOptions=["DNS_TIME","TCP_HANDSHAKE","RESPONSE_TIME","SECURE_CONNECTION_TIME","FETCH_UNTIL_RESPONSE","REQ_START_UNTIL_RES_END","START_UNTIL_RES_END","REDIRECT_TIME",];// run em all!// https://developer.mozilla.org/en-US/docs/Web/API/Resource_Timing_API/Using_the_Resource_Timing_API#timing_resource_loading_phasestimingOptions.forEach((timing)=>{console.groupCollapsed(`FIRST PARTY:${timing}`);console.table(calculateTimings("first",timing));console.groupEnd();console.groupCollapsed(`THIRD PARTY:${timing}`);console.table(calculateTimings("third",timing));console.groupEnd();});// choose your battle - arg1 is string either "first" or "third", arg2 is string timing option listed above.console.table(calculateTimings("first","REQ_START_UNTIL_RES_END"));

Inline Script Info and Size

Find all inline scripts on the page and list the scripts and count. Find the total byte size of all the inline scripts in the console.

functionfindInlineScripts(){constinlineScripts=document.querySelectorAll(["script:not([async]):not([defer]):not([src])"])console.log(inlineScripts)console.log(`COUNT:${inlineScripts.length}`)lettotalByteSize=0letNEXT_DATA_SIZE=0for(constscriptof[...inlineScripts]){consthtml=script.innerHTMLconstsize=newBlob([html]).sizeif(script.id==="__NEXT_DATA__"){NEXT_DATA_SIZE+=size}totalByteSize+=sizereturn{totalByteSize:(totalByteSize/1000)+" kb",NEXT_DATA_SIZE:NEXT_DATA_SIZE===0 ?(NEXT_DATA_SIZE/1000) :0}}}console.log(findInlineScripts())

Inline Script Info and Size Including__NEXT_DATA__

Find all inline scripts and their total size separately from__NEXT_DATA__ serialized JSON inline Script

functionfindInlineScriptsWithNextData(){constinlineScripts=document.querySelectorAll(["script:not([async]):not([defer]):not([src])"]);console.log(inlineScripts);console.log(`COUNT:${inlineScripts.length}`);constbyteSize={NEXT_DATA_SIZE:0,OTHER_SIZE:0};functiongetSize(script){consthtml=script.innerHTML;returnnewBlob([html]).size;}functionconvertToKb(bytes){returnbytes/1000;}for(constscriptof[...inlineScripts]){if(script.id=="__NEXT_DATA__"){byteSize.NEXT_DATA_SIZE+=getSize(script);}else{byteSize.OTHER_SIZE+=getSize(script);}}return{NEXT_DATA_SIZE:convertToKb(byteSize.NEXT_DATA_SIZE)+" kb",OTHER_SIZE:convertToKb(byteSize.OTHER_SIZE)+" kb",totalByteSize:convertToKb(byteSize.NEXT_DATA_SIZE)+convertToKb(byteSize.OTHER_SIZE)+" kb"};}console.log(findInlineScriptsWithNextData());

Get your<head> in order

How you order elements in the can have an effect on the (perceived) performance of the page.

Usecapo.js theRick Viscomi script

e.g. web.dev

image

Interaction

Long Task

To determine when long tasks happen, you can usePerformanceObserver and register to observe entries of typelongtask:

try{// Create the performance observer.constpo=newPerformanceObserver((list)=>{for(constentryoflist.getEntries()){// Log the entry and all associated details.console.table(entry.toJSON());}});// Start listening for `longtask` entries to be dispatched.po.observe({type:"longtask",buffered:true});}catch(e){console.error(`The browser doesn't support this API`);}

Layout Shifts

To find more specific information about layout shifts, you can usePerformanceObserver and register to observe entries of typelayout-shift:

functiongenColor(){letn=(Math.random()*0xfffff*1000000).toString(16);return"#"+n.slice(0,6);}// console.log(shifts) to see full list of shifts above thresholdconstshifts=[];// threshold ex: 0.05// Layout Shifts will be grouped by color.// All nodes attributed to the shift will have a border with the corresponding color// Shift value will be added above parent node.// Will have all details related to that shift in dropdown// Useful for single page applications and finding shifts after initial loadfunctionfindShifts(threshold){returnnewPerformanceObserver((list)=>{list.getEntries().forEach((entry)=>{if(entry.value>threshold&&!entry.hadRecentInput){constcolor=genColor();shifts.push(entry);console.log(shifts);constvalueNode=document.createElement("details");valueNode.innerHTML=`        <summary>Layout Shift:${entry.value}</summary>        <pre>${JSON.stringify(entry,null,2)}</pre>        `;valueNode.style=`color:${color};`;entry.sources.forEach((source)=>{source.node.parentNode.insertBefore(valueNode,source.node);source.node.style=`border: 2px${color} solid`;});}});});}findShifts(0.05).observe({entryTypes:["layout-shift"]});

Print al the CLS metrics when load the page and the user interactive with the page:

newPerformanceObserver((entryList)=>{console.log(entryList.getEntries());}).observe({type:"layout-shift",buffered:true});

About

⚡️ 💾 Web Performance Snippets

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp