web-vitals
Version:
Easily measure performance metrics in JavaScript
2 lines (1 loc) • 11.7 kB
JavaScript
var webVitals=function(t){"use strict";class e{t;i=0;o=[];u(t){if(t.hadRecentInput)return;const e=this.o[0],n=this.o.at(-1);this.i&&e&&n&&t.startTime-n.startTime<1e3&&t.startTime-e.startTime<5e3?(this.i+=t.value,this.o.push(t)):(this.i=t.value,this.o=[t]),this.t?.(t)}}const n=()=>{const t=performance.getEntriesByType("navigation")[0];if(t&&t.responseStart>0&&t.responseStart<performance.now())return t},i=t=>{if("loading"===document.readyState)return"loading";const e=n();if(e){if(t<e.domInteractive)return"loading";if(0===e.domContentLoadedEventStart||t<e.domContentLoadedEventStart)return"dom-interactive";if(0===e.domComplete||t<e.domComplete)return"dom-content-loaded"}return"complete"},o=t=>{const e=t.nodeName;return 1===t.nodeType?e.toLowerCase():e.toUpperCase().replace(/^#/,"")},r=t=>{let e="";try{for(;9!==t?.nodeType;){const n=t,i=n.id?"#"+n.id:[o(n),...Array.from(n.classList).sort()].join(".");if(e.length+i.length>99)return e||i;if(e=e?i+">"+e:i,n.id)break;t=n.parentNode}}catch{}return e},s=new WeakMap;function a(t,e){let n=s.get(e);return n||(n=new WeakMap,s.set(e,n)),n.get(t)||n.set(t,new e),n.get(t)}let c=-1;const u=()=>c,f=t=>{addEventListener("pageshow",e=>{e.persisted&&(c=e.timeStamp,t(e))},!0)},l=(t,e,n,i)=>{let o,r;return s=>{e.value>=0&&(s||i)&&(r=e.value-(o??0),(r||void 0===o)&&(o=e.value,e.delta=r,e.rating=((t,e)=>t>e[1]?"poor":t>e[0]?"needs-improvement":"good")(e.value,n),t(e)))}},d=t=>{requestAnimationFrame(()=>requestAnimationFrame(t))},h=()=>n()?.activationStart??0,m=(t,e=-1)=>{const i=n();let o="navigate";u()>=0?o="back-forward-cache":i&&(document.prerendering||h()>0?o="prerender":document.wasDiscarded?o="restore":i.type&&(o=i.type.replace(/_/g,"-")));return{name:t,value:e,rating:"good",delta:0,entries:[],id:`v5-${Date.now()}-${Math.floor(8999999999999*Math.random())+1e12}`,navigationType:o}},g=(t,e,n={})=>{try{if(PerformanceObserver.supportedEntryTypes.includes(t)){const i=new PerformanceObserver(t=>{queueMicrotask(()=>{e(t.getEntries())})});return i.observe({type:t,buffered:!0,...n}),i}}catch{}},p=t=>{let e=!1;return()=>{e||(t(),e=!0)}};let y=-1;const v=new Set,b=()=>"hidden"!==document.visibilityState||document.prerendering?1/0:0,M=t=>{if("hidden"===document.visibilityState){if("visibilitychange"===t.type)for(const t of v)t();isFinite(y)||(y="visibilitychange"===t.type?t.timeStamp:0,removeEventListener("prerenderingchange",M,!0))}},T=()=>{if(y<0){const t=h(),e=document.prerendering?void 0:globalThis.performance.getEntriesByType("visibility-state").find(e=>"hidden"===e.name&&e.startTime>=t)?.startTime;y=e??b(),addEventListener("visibilitychange",M,!0),addEventListener("prerenderingchange",M,!0),f(()=>{setTimeout(()=>{y=b()})})}return{get firstHiddenTime(){return y},onHidden(t){v.add(t)}}},E=t=>{document.prerendering?addEventListener("prerenderingchange",t,!0):t()},D=[1800,3e3],L=(t,e={})=>{E(()=>{const n=T();let i,o=m("FCP");const r=g("paint",t=>{for(const e of t)"first-contentful-paint"===e.name&&(r.disconnect(),e.startTime<n.firstHiddenTime&&(o.value=Math.max(e.startTime-h(),0),o.entries.push(e),i(!0)))});r&&(i=l(t,o,D,e.reportAllChanges),f(n=>{o=m("FCP"),i=l(t,o,D,e.reportAllChanges),d(()=>{o.value=performance.now()-n.timeStamp,i(!0)})}))})},S=[.1,.25],P=t=>t.find(t=>1===t.node?.nodeType)||t[0];let w=0,k=1/0,_=0;const F=t=>{for(const e of t)e.interactionId&&(k=Math.min(k,e.interactionId),_=Math.max(_,e.interactionId),w=_?(_-k)/7+1:0)};let B;const C=()=>B?w:performance.interactionCount??0,O=()=>{"interactionCount"in performance||B||(B=g("event",F,{durationThreshold:0}))};let j=0;class I{l=[];h=new Map;m;p;v(){j=C(),this.l.length=0,this.h.clear()}M(){const t=Math.min(this.l.length-1,Math.floor((C()-j)/50));return this.l[t]}u(t){if(this.m?.(t),!t.interactionId&&"first-input"!==t.entryType)return;const e=this.l.at(-1);let n=this.h.get(t.interactionId);if(n||this.l.length<10||t.duration>e.T){if(n?t.duration>n.T?(n.entries=[t],n.T=t.duration):t.duration===n.T&&t.startTime===n.entries[0].startTime&&n.entries.push(t):(n={id:t.interactionId,entries:[t],T:t.duration},this.h.set(n.id,n),this.l.push(n)),this.l.sort((t,e)=>e.T-t.T),this.l.length>10){const t=this.l.splice(10);for(const e of t)this.h.delete(e.id)}this.p?.(n)}}}const A=t=>{const e=globalThis.requestIdleCallback||setTimeout,n=globalThis.cancelIdleCallback||clearTimeout;if("hidden"===document.visibilityState)t();else{const i=p(t);let o=-1;const r=()=>{n(o),i()};addEventListener("visibilitychange",r,{once:!0,capture:!0}),o=e(()=>{removeEventListener("visibilitychange",r,{capture:!0}),i()})}},W=[200,500];class q{m;u(t){this.m?.(t)}}const N=[2500,4e3],V=[800,1800],$=t=>{document.prerendering?E(()=>$(t)):"complete"!==document.readyState?addEventListener("load",()=>$(t),!0):setTimeout(t)};return t.CLSThresholds=S,t.FCPThresholds=D,t.INPThresholds=W,t.LCPThresholds=N,t.TTFBThresholds=V,t.onCLS=(t,n={})=>{const o=a(n=Object.assign({},n),e),s=new WeakMap;o.t=t=>{if(t?.sources?.length){const e=P(t.sources),i=e?.node;if(i){const t=n.generateTarget?.(i)??r(i);s.set(e,t)}}};((t,n={})=>{const i=T();L(p(()=>{let o,r=m("CLS",0);const s=a(n,e),c=t=>{for(const e of t)s.u(e);s.i>r.value&&(r.value=s.i,r.entries=s.o,o())},u=g("layout-shift",c);u&&(o=l(t,r,S,n.reportAllChanges),i.onHidden(()=>{c(u.takeRecords()),o(!0)}),f(()=>{s.i=0,r=m("CLS",0),o=l(t,r,S,n.reportAllChanges),d(o)}),setTimeout(o))}))})(e=>{t((t=>{let e={};if(t.entries.length){const n=t.entries.reduce((t,e)=>t.value>e.value?t:e);if(n?.sources?.length){const t=P(n.sources);t&&(e={largestShiftTarget:s.get(t),largestShiftTime:n.startTime,largestShiftValue:n.value,largestShiftSource:t,largestShiftEntry:n,loadState:i(n.startTime)})}}return Object.assign(t,{attribution:e})})(e))},n)},t.onFCP=(t,e={})=>{L(e=>{t((t=>{let e={timeToFirstByte:0,firstByteToFCP:t.value,loadState:i(u())};if(t.entries.length){const o=n(),r=t.entries.at(-1);if(o){const n=o.activationStart||0,s=Math.max(0,o.responseStart-n);e={timeToFirstByte:s,firstByteToFCP:t.value-s,loadState:i(t.entries[0].startTime),navigationEntry:o,fcpEntry:r}}}return Object.assign(t,{attribution:e})})(e))},e)},t.onINP=(t,e={})=>{const n=a(e=Object.assign({},e),I);let o=[],s=[],c=0;const u=new WeakMap,d=new WeakMap;let h=!1;const p=()=>{h||(A(y),h=!0)},y=()=>{const t=new Set(n.l.map(t=>u.get(t.entries[0]))),e=s.length-10;s=s.filter((n,i)=>i>=e||t.has(n));const i=new Set;for(const t of s){const e=v(t.startTime,t.processingEnd);for(const t of e)i.add(t)}o=o.filter(t=>t.startTime>c||i.has(t)),h=!1};n.m=t=>{const n=t.startTime+t.duration;let i;c=Math.max(c,t.processingEnd);for(let o=s.length-1;o>=0;o--){const r=s[o];if(Math.abs(n-r.renderTime)<=8){i=r,i.startTime=Math.min(t.startTime,i.startTime),i.processingStart=Math.min(t.processingStart,i.processingStart),i.processingEnd=Math.max(t.processingEnd,i.processingEnd),!1!==e.includeProcessedEventEntries&&i.entries.push(t);break}}i||(i={startTime:t.startTime,processingStart:t.processingStart,processingEnd:t.processingEnd,renderTime:n,entries:!1!==e.includeProcessedEventEntries?[t]:[]},s.push(i)),(t.interactionId||"first-input"===t.entryType)&&u.set(t,i),p()},n.p=t=>{if(!d.get(t)){const n=t.entries.find(t=>t.target)?.target;if(n){const i=e.generateTarget?.(n)??r(n);d.set(t,i)}else{const e=t.entries.find(t=>t.targetSelector)?.targetSelector;e&&d.set(t,e)}}};const v=(t,e)=>{const n=[];for(const i of o)if(!(i.startTime+i.duration<t)){if(i.startTime>e)break;n.push(i)}return n},b=t=>{const e=t.entries[0],o=u.get(e),r=e.processingStart,s=Math.max(e.startTime+e.duration,r),a=Math.min(o.processingEnd,s),c=o.entries.sort((t,e)=>t.processingStart-e.processingStart),f=v(e.startTime,a),l=n.h.get(e.interactionId),h={interactionTarget:d.get(l),interactionType:e.name.startsWith("key")?"keyboard":"pointer",interactionTime:e.startTime,nextPaintTime:s,processedEventEntries:c,longAnimationFrameEntries:f,inputDelay:r-e.startTime,processingDuration:a-r,presentationDelay:s-a,loadState:i(e.startTime),longestScript:void 0,totalScriptDuration:void 0,totalStyleAndLayoutDuration:void 0,totalPaintDuration:void 0,totalUnattributedDuration:void 0};return(t=>{if(!t.longAnimationFrameEntries?.length)return;const e=t.interactionTime,n=t.inputDelay,i=t.processingDuration;let o,r,s=0,a=0,c=0,u=0;for(const c of t.longAnimationFrameEntries){a=a+c.startTime+c.duration-c.styleAndLayoutStart;for(const t of c.scripts){const c=t.startTime+t.duration;if(c<e)continue;const f=c-Math.max(e,t.startTime),l=t.duration?f/t.duration*t.forcedStyleAndLayoutDuration:0;s+=f-l,a+=l,f>u&&(r=t.startTime<e+n?"input-delay":t.startTime>=e+n+i?"presentation-delay":"processing-duration",o=t,u=f)}}const f=t.longAnimationFrameEntries.at(-1),l=f?f.startTime+f.duration:0;l>=e+n+i&&(c=t.nextPaintTime-l),o&&r&&(t.longestScript={entry:o,subpart:r,intersectingDuration:u}),t.totalScriptDuration=s,t.totalStyleAndLayoutDuration=a,t.totalPaintDuration=c,t.totalUnattributedDuration=t.nextPaintTime-e-s-a-c})(h),Object.assign(t,{attribution:h})};g("long-animation-frame",t=>{o=o.concat(t),p()}),((t,e={})=>{if(!globalThis.PerformanceEventTiming||!("interactionId"in PerformanceEventTiming.prototype))return;const n=T();E(()=>{O();let i,o=m("INP");const r=a(e,I),s=t=>{A(()=>{for(const e of t)r.u(e);const e=r.M();e&&e.T!==o.value&&(o.value=e.T,o.entries=e.entries,i())})},c=g("event",s,{durationThreshold:e.durationThreshold??40});i=l(t,o,W,e.reportAllChanges),c&&(c.observe({type:"first-input",buffered:!0}),n.onHidden(()=>{s(c.takeRecords()),i(!0)}),f(()=>{r.v(),o=m("INP"),i=l(t,o,W,e.reportAllChanges)}))})})(e=>{t(b(e))},e)},t.onLCP=(t,e={})=>{const i=a(e=Object.assign({},e),q),o=new WeakMap;i.m=t=>{const n=t.element;if(n){const i=e.generateTarget?.(n)??r(n);o.set(t,i)}else t.id&&o.set(t,`#${t.id}`)};((t,e={})=>{E(()=>{const n=T();let i,o=m("LCP");const r=a(e,q),s=t=>{e.reportAllChanges||(t=t.slice(-1));for(const e of t)r.u(e),e.startTime<n.firstHiddenTime&&(o.value=Math.max(e.startTime-h(),0),o.entries=[e],i())},c=g("largest-contentful-paint",s);if(c){i=l(t,o,N,e.reportAllChanges);const n=p(()=>{s(c.takeRecords()),c.disconnect(),i(!0)}),r=t=>{t.isTrusted&&(A(n),removeEventListener(t.type,r,{capture:!0}))};for(const t of["keydown","click","visibilitychange"])addEventListener(t,r,{capture:!0});f(n=>{o=m("LCP"),i=l(t,o,N,e.reportAllChanges),d(()=>{o.value=performance.now()-n.timeStamp,i(!0)})})}})})(e=>{t((t=>{let e={timeToFirstByte:0,resourceLoadDelay:0,resourceLoadDuration:0,elementRenderDelay:t.value};if(t.entries.length){const i=t.entries.at(-1),r=i.url&&performance.getEntriesByType("resource").find(t=>t.name===i.url);e.target=o.get(i),e.lcpEntry=i,i.url&&(e.url=i.url),r&&(e.lcpResourceEntry=r);const s=n();if(s){const n=s.activationStart||0,i=Math.max(0,s.responseStart-n),o=Math.max(i,r?(r.requestStart||r.startTime)-n:0),a=Math.min(t.value,Math.max(o,r?r.responseEnd-n:0));e={...e,timeToFirstByte:i,resourceLoadDelay:o-i,resourceLoadDuration:a-o,elementRenderDelay:t.value-a,navigationEntry:s}}}return Object.assign(t,{attribution:e})})(e))},e)},t.onTTFB=(t,e={})=>{((t,e={})=>{let i=m("TTFB"),o=l(t,i,V,e.reportAllChanges);$(()=>{const r=n();r&&(i.value=Math.max(r.responseStart-h(),0),i.entries=[r],o(!0),f(()=>{i=m("TTFB",0),o=l(t,i,V,e.reportAllChanges),o(!0)}))})})(e=>{t((t=>{let e={waitingDuration:0,cacheDuration:0,dnsDuration:0,connectionDuration:0,requestDuration:0};if(t.entries.length){const n=t.entries[0],i=n.activationStart||0,o=Math.max((n.workerStart||n.fetchStart)-i,0),r=Math.max(n.domainLookupStart-i,0),s=Math.max(n.connectStart-i,0),a=Math.max(n.connectEnd-i,0);e={waitingDuration:o,cacheDuration:r-o,dnsDuration:s-r,connectionDuration:a-s,requestDuration:t.value-a,navigationEntry:n}}return Object.assign(t,{attribution:e})})(e))},e)},t}({});