Page Speed is a feature, and to deliver it we need to understand the many factors and fundamental limitations that are at play. If we can measure it, we can improve it.
Star Follow @zizzamiaPerfume is a tiny, web performance monitoring library that reports field data back to your favorite analytics tool.
Perfume leverages the latest Performance APIs to collect field data that allows us to understand what real-world users are actually experiencing.
With Perfume.js, you can collect these metrics to develop a deeper understanding of how customers around the world perceive web performance for your application.
Use your favorite analytics tool to visualize the data from country to country. Take a look at this example comparing FCP for coinbase.com in the United States, Italy, Indonesia, and Nigeria.
// Install npm install perfume.js --save // Importing library // Import the generated bundle to use the whole library generated: import Perfume from 'perfume.js'; // Universal Module Definition: import Perfume from 'node_modules/perfume.js/perfume.umd.js'; |
Metrics like Navigation Timing, Network Information, FP, FCP, FID, LCP, CLS and TBT are default reported with Perfume; All results will be reported to the analyticsTracker callback, and the code below is just one way for you to organize your tracking, feel free to tweak it suit your needs.
Oh btw, you're being served a
lighter experience based on your hardware,
network conditions and data saver preference.
// Device Information
Network information: --
Device Memory: --
Hardware Concurrency:
--
Data Saver preference: false
// Main Performance Metrics
Time To First Byte: 0 ms
First Paint: -- ms
First Contentful Paint: -- ms
First Input Delay: -- ms
Largest Contentful Paint: -- ms
Cumulative Layout Shift: -- score
Total Blocking Time: -- ms
// Secondary Performance Metrics
// These metrics activate on a set delay or when the tab changes
visibility
Largest Contentful Paint Final: -- ms
Cumulative Layout Shift Final: --
Total Blocking Time 5S: -- ms
Total Blocking Time 10S: -- ms
Total Blocking Time Final: -- ms
// Experimental Performance metric
dataConsumption: --
const perfume = new Perfume({ analyticsTracker: (options) => { const { metricName, data, navigatorInformation } = options; switch (metricName) { case 'navigationTiming': if (data && data.timeToFirstByte) { myAnalyticsTool.track('navigationTiming', data); } break; case 'networkInformation': if (data && data.effectiveType) { myAnalyticsTool.track('networkInformation', data); } break; case 'fp': myAnalyticsTool.track('firstPaint', { duration: data }); break; case 'fcp': myAnalyticsTool.track('firstContentfulPaint', { duration: data }); break; case 'fid': myAnalyticsTool.track('firstInputDelay', { duration: data }); break; case 'lcp': myAnalyticsTool.track('largestContentfulPaint', { duration: data }); break; case 'lcpFinal': myAnalyticsTool.track('largestContentfulPaintFinal', { duration: data }); break; case 'cls': myAnalyticsTool.track('cumulativeLayoutShift', { duration: data }); break; case 'clsFinal': myAnalyticsTool.track('cumulativeLayoutShiftFinal', { duration: data }); break; case 'tbt': myAnalyticsTool.track('totalBlockingTime', { duration: data }); break; case 'tbt5S': myAnalyticsTool.track('totalBlockingTime5S', { duration: data }); break; case 'tbt10S': myAnalyticsTool.track('totalBlockingTime10S', { duration: data }); break; case 'tbtFinal': myAnalyticsTool.track('totalBlockingTimeFinal', { duration: data }); break; default: myAnalyticsTool.track(metricName, { duration: data }); break; } }, }); |
In a world with widely varying device capabilities, a one-size-fits-all event doesnβt always work. Perfume adds data enrichment to all events so we can better understand the real world experiences:
Based on the Navigator APIs the library can help us differentiate between a low-end and a high-end device/experience:
Coo coo coo cool, let's learn something new about measuring page's speed performance.
Default options provided to Perfume.js constructor.
const options = { resourceTiming: false, analyticsTracker: options => {}, maxMeasureTime: 15000, }; |
Code and documentation copyright 2020 Leonardo Zizzamia. Code released under the MIT license. Docs released under Creative Commons.