web-vitals-element
Version:
> Bring [web vitals](https://github.com/GoogleChrome/web-vitals) quickly into your page using custom elements
2 lines (1 loc) • 8.26 kB
JavaScript
var e,t,n,i,r=function(e,t){return{name:e,value:void 0===t?-1:t,delta:0,entries:[],id:"v2-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12)}},a=function(e,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){if("first-input"===e&&!("PerformanceEventTiming"in self))return;var n=new PerformanceObserver((function(e){return e.getEntries().map(t)}));return n.observe({type:e,buffered:!0}),n}}catch(e){}},o=function(e,t){var n=function n(i){"pagehide"!==i.type&&"hidden"!==document.visibilityState||(e(i),t&&(removeEventListener("visibilitychange",n,!0),removeEventListener("pagehide",n,!0)))};addEventListener("visibilitychange",n,!0),addEventListener("pagehide",n,!0)},s=function(e){addEventListener("pageshow",(function(t){t.persisted&&e(t)}),!0)},d="function"==typeof WeakSet?new WeakSet:new Set,u=function(e,t,n){var i;return function(){t.value>=0&&(n||d.has(t)||"hidden"===document.visibilityState)&&(t.delta=t.value-(i||0),(t.delta||void 0===i)&&(i=t.value,e(t)))}},c=-1,l=function(){return"hidden"===document.visibilityState?0:1/0},m=function(){o((function(e){var t=e.timeStamp;c=t}),!0)},p=function(){return c<0&&(c=l(),m(),s((function(){setTimeout((function(){c=l(),m()}),0)}))),{get firstHiddenTime(){return c}}},f=function(e,t){var n,i=p(),o=r("FCP"),c=function(e){"first-contentful-paint"===e.name&&(m&&m.disconnect(),e.startTime<i.firstHiddenTime&&(o.value=e.startTime,o.entries.push(e),d.add(o),n()))},l=performance.getEntriesByName&&performance.getEntriesByName("first-contentful-paint")[0],m=l?null:a("paint",c);(l||m)&&(n=u(e,o,t),l&&c(l),s((function(i){o=r("FCP"),n=u(e,o,t),requestAnimationFrame((function(){requestAnimationFrame((function(){o.value=performance.now()-i.timeStamp,d.add(o),n()}))}))})))},v=!1,h=-1,g={passive:!0,capture:!0},b=new Date,y=function(i,r){e||(e=r,t=i,n=new Date,E(removeEventListener),w())},w=function(){if(t>=0&&t<n-b){var r={entryType:"first-input",name:e.type,target:e.target,cancelable:e.cancelable,startTime:e.timeStamp,processingStart:e.timeStamp+t};i.forEach((function(e){e(r)})),i=[]}},T=function(e){if(e.cancelable){var t=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,t){var n=function(){y(e,t),r()},i=function(){r()},r=function(){removeEventListener("pointerup",n,g),removeEventListener("pointercancel",i,g)};addEventListener("pointerup",n,g),addEventListener("pointercancel",i,g)}(t,e):y(t,e)}},E=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(t){return e(t,T,g)}))},L=Object.freeze({__proto__:null,getCLS:function(e,t){v||(f((function(e){h=e.value})),v=!0);var n,i=function(t){h>-1&&e(t)},d=r("CLS",0),c=0,l=[],m=function(e){if(!e.hadRecentInput){var t=l[0],i=l[l.length-1];c&&e.startTime-i.startTime<1e3&&e.startTime-t.startTime<5e3?(c+=e.value,l.push(e)):(c=e.value,l=[e]),c>d.value&&(d.value=c,d.entries=l,n())}},p=a("layout-shift",m);p&&(n=u(i,d,t),o((function(){p.takeRecords().map(m),n()})),s((function(){c=0,h=-1,d=r("CLS",0),n=u(i,d,t)})))},getFCP:f,getFID:function(n,c){var l,m=p(),f=r("FID"),v=function(e){e.startTime<m.firstHiddenTime&&(f.value=e.processingStart-e.startTime,f.entries.push(e),d.add(f),l())},h=a("first-input",v);l=u(n,f,c),h&&o((function(){h.takeRecords().map(v),h.disconnect()}),!0),h&&s((function(){var a;f=r("FID"),l=u(n,f,c),i=[],t=-1,e=null,E(addEventListener),a=v,i.push(a),w()}))},getLCP:function(e,t){var n,i=p(),c=r("LCP"),l=function(e){var t=e.startTime;t<i.firstHiddenTime&&(c.value=t,c.entries.push(e)),n()},m=a("largest-contentful-paint",l);if(m){n=u(e,c,t);var f=function(){d.has(c)||(m.takeRecords().map(l),m.disconnect(),d.add(c),n())};["keydown","click"].forEach((function(e){addEventListener(e,f,{once:!0,capture:!0})})),o(f,!0),s((function(i){c=r("LCP"),n=u(e,c,t),requestAnimationFrame((function(){requestAnimationFrame((function(){c.value=performance.now()-i.timeStamp,d.add(c),n()}))}))}))}},getTTFB:function(e){var t,n=r("TTFB");t=function(){try{var t=performance.getEntriesByType("navigation")[0]||function(){var e=performance.timing,t={entryType:"navigation",startTime:0};for(var n in e)"navigationStart"!==n&&"toJSON"!==n&&(t[n]=Math.max(e[n]-e.navigationStart,0));return t}();if(n.value=n.delta=t.responseStart,n.value<0)return;n.entries=[t],e(n)}catch(e){}},"complete"===document.readyState?setTimeout(t,0):addEventListener("pageshow",t)}});const S=new Map([["CLS",{thresholds:{good:.1,needsImprovement:.25},observerEntryType:"layout-shift",explainerURL:"https://web.dev/cls/",longName:"Cumulative Layout Shift",roundFn:e=>Math.floor(100*e)/100}],["FCP",{thresholds:{good:2500},observerEntryType:"paint",explainerURL:"https://web.dev/fcp/",unit:"ms",longName:"First Contentful Paint"}],["FID",{thresholds:{good:100,needsImprovement:300},observerEntryType:"first-input",explainerURL:"https://web.dev/fid/",unit:"ms",longName:"First Input Delay"}],["LCP",{thresholds:{good:2500,needsImprovement:4e3},observerEntryType:"paint",explainerURL:"https://web.dev/lcp/",unit:"ms",longName:"Largest Contentful Paint"}],["TTFB",{thresholds:{good:2500},explainerURL:"https://web.dev/time-to-first-byte/",unit:"ms",longName:"Time to first byte"}]]),C=["class","style"],F=["show-unsupported","show-metric-name"];class M extends HTMLElement{constructor(){super(),this.unsupportedMetrics=[],this.metrics=new Map}connectedCallback(){const e=this.getMetricAttributes(),t=e.length?e:[...S.keys()];this.metrics=this.getMetrics(t),this.render();for(let e of this.metrics.values()){const{name:t,getWebVitalsValue:n}=e;n((n=>{this.metrics.set(t,{...e,...n}),this.render()}),!0)}}getMetricAttributes(){return this.getAttributeNames().filter((e=>!C.includes(e)&&!F.includes(e))).map((e=>e.toUpperCase()))}getMetrics(e){return new Map(e.reduce(((e,t)=>{const n=L[`get${t}`];if(!n)return console.error(`${t} is not supported by '<web-vitals />'`),this.unsupportedMetrics.push(t),e;const i=S.get(t),{observerEntryType:r}=i;return r&&!PerformanceObserver.supportedEntryTypes.includes(r)?(console.error(`${t} is not supported by your browser`),this.unsupportedMetrics.push(t),e):[...e,[t,{...S.get(t),getWebVitalsValue:n,name:t}]]}),[]))}render(){this.innerHTML=`<div class="web-vitals">\n <dl>\n ${[...this.metrics].map((([e,t])=>{const{explainerURL:n,longName:i,roundFn:r,thresholds:a,unit:o,value:s}=t;let d="";const u=r||Math.floor,{good:c,needsImprovement:l}=a;if(s){d+="is-final ";let e="is-poor";l&&s<=l&&(e="needs-improvement"),s<=c&&(e="is-good"),d+=e}return`\n <div class="${d}">\n <dt>\n ${this.hasAttribute("show-metric-name")?`${i} (<a href="${n}">${e}</a>)`:`<a href="${n}">${e}</a>`}\n </dt>\n <dd>${s?`${u(s)}${o||""}`:"..."}</dd>\n </div>\n `})).join("")}\n </dl>\n ${this.unsupportedMetrics.length&&this.hasAttribute("show-unsupported")?`<p>Not supported: ${this.unsupportedMetrics.join(", ")}</p>`:""}\n </div>`}}!function(e,t){void 0===t&&(t={});var n=t.insertAt;if(e&&"undefined"!=typeof document){var i=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===n&&i.firstChild?i.insertBefore(r,i.firstChild):i.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}(".web-vitals {\n max-width: 20em;\n border-radius: 0.5em;\n overflow: hidden;\n padding: 1em;\n font-family: Arial, Helvetica, sans-serif;\n box-shadow: 0 0.25em 0.35em rgba(23, 23, 23, 0.4);\n color: #444;\n background: #fff;\n}\n\n.web-vitals a {\n color: #444;\n font-weight: bold;\n}\n\n.web-vitals dl {\n margin: 0;\n grid-template-columns: 1fr 1fr;\n}\n\n.web-vitals p {\n margin: 0.5em 0 0;\n font-size: 0.75em;\n}\n\n.web-vitals div {\n display: grid;\n grid-template-columns: 3fr 1fr;\n}\n\n.web-vitals div dd::after {\n margin-left: 0.25em;\n line-height: 1;\n}\n\n.web-vitals div:not(.is-done) dd::after {\n content: '🕐';\n}\n\n.web-vitals div.is-good dd::after {\n content: '✅';\n}\n\n.web-vitals div.needs-improvement dd::after {\n content: '⚠️';\n}\n\n.web-vitals div.is-poor dd::after {\n content: '❌';\n}\n\n.web-vitals dd {\n text-align: right;\n margin-left: 1em;\n}\n"),customElements.define("web-vitals",M);