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