Repository files navigation

react-component-performance

Monitor performance at a per component level

Current state is RFC 📄

If you like this idea, or have know of something like this that already exists, or have feedback before I start making anything, let me know!

Motivation for this tool

We want to measure the load time of our apps in a way that,

  • Meaningfully reflects real user experiences, including geography, devices, network conditions
  • Works for single page applications that progressively load parts of the app ("cold" vs. "warm" page loads)
  • Is easily comparible between applications

There are a number of performance metrics that already exist

Ways of measuring performance

  • window.onload timing
  • Above-the-fold render time (ATF)
    • Measurable with webpagetest.org
  • Time to first paint
  • Time to first contentful paint
  • Time to first meaningful paint
  • Apdex (uses timings to create an index)

Measuring Single page app performance

  • window.onload just doesn't work for SPA's, it's not triggered for subsequent page loads, or at the right time
  • Above-the-fold render time doesn't work for real traffic, but it does give a good impression with simulated traffic.
  • "Apdex" is not easy to compare (with different t values), and does not define what a "satisfactory" page load is.
  • There is no such thing as "load time" as a single number. We want to represent a much richer picture.
    • We represent many different experiences (cold page load, warm page load)
    • We represent many different environments (network conditions, geographical location)
    • However, we need to reduce it to a single number for KPI's, OKR's, etc.
    • We want to compare fairly with other applications

First "meaningful" paint

First meaningful paint provides a good way of measuring user experience, but requires knowledge of what "meaningful" is.

We also still need a good way to measure load times across "warm" page loads, as the first paint isn't the only one!

⏰ react-component-timing

React component timing is a tool that helps you get the above data, so that when you try to move the needle, you actually move it for your users.

  • It lets you define what a meaningful paint is for a React app
  • It breaks down timings by component, so that you can see how your app progressively loads.
  • It provides timings via the User timing API that are easily comparible across different experiences.
  • It provides a pluggable layer that fits into your existing tools: New Relic, Google Analytics, etc.

API

import*asReactfrom"react";import{ReactComponentTimingProvider}from"react-component-timing";import{newRelicIntegration}from"./new-relic-timing-reporter";importwithDatafrom"./app-data-provider";exportclassAppImplextendsReact.Component{checkLoaded({ childTimings }){/* We have access to the timings of all of the children, through some magic */return(childTimings.nav.loaded&&childTimings.article.loaded&&this.props.data.loaded);}render(){return(<ReactComponentTimingProviderreporter={newRelicIntegration}><Page><ReactComponentTimingcomponentName="page"checkLoaded={this.checkLoaded}><Nav/><Content><Article/><Comments/></Content></ReactComponentTiming></Page></ReactComponentTimingProvider>);}}exportconstApp=withData(AppImpl);
import*asReactfrom"react";import{ReactCompomnentTiming}from"react-component-timing";import{NavigationInner}from"./navigation-inner";importwithDatafrom"./nav-data-provider";classNavImplextendsReact.Component{checkLoaded(){returnthis.props.data.loaded;}render(){return(<><ReactCompomnentTimingcomponentName="nav"checkLoaded={this.checkLoaded}/><NavigationInner/></>);}}exportconstNav=withData(NavImpl);

(And similar for Comments and Article, which would both include dynamically loaded data)

API Concepts

Events

  • Load: a component transitioned from "isLoading: false" -> true -> false. The time taken between falses is reported as a "load" event
    • Metadata:
      • Props given to the component during the transition
      • Page path
  • Render: a component entered a render state

How it would work

✨ Through some wizardry and probably some API changes from the above, I think it'd be possible to implement something that would build a picture of the timing of when these "timing" components got rendered, and when they reported that they were loaded.

When props change (and are rerendered), a component can go into and out of a loading state. This loading state, and the reasons why, would be captured by the reporter.

This would let you define custom metrics, for, say, the comments component. You would be able to know a performance timing from cold page load to the comments being loaded, and how that is different on subsequent warm page loads.

The API also allows you to define "loading" states by composing your child loading states (possibly excluding some if they do not constitute "meaningful" for the parent component).


Additional reading

Goals for performance

For what targets to hit, the rail guideline provides good information.

  • Focus on the user.
  • Respond to user input in under 100ms.
  • Produce a frame in under 10ms when animating or scrolling.
  • Maximize main thread idle time.
  • Load interactive content in under 5000ms.

The RAIL framework: _ Response _ Animation _ Idle _ Load

This tool will help measure the Load and Response parts of this framework.

About

Monitor performance at a per component level

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

react-component-performance

Monitor performance at a per component level

Current state is RFC 📄

If you like this idea, or have know of something like this that already exists, or have feedback before I start making anything, let me know!

Motivation for this tool

We want to measure the load time of our apps in a way that,

  • Meaningfully reflects real user experiences, including geography, devices, network conditions
  • Works for single page applications that progressively load parts of the app ("cold" vs. "warm" page loads)
  • Is easily comparible between applications

There are a number of performance metrics that already exist

Ways of measuring performance

  • window.onload timing
  • Above-the-fold render time (ATF)
    • Measurable with webpagetest.org
  • Time to first paint
  • Time to first contentful paint
  • Time to first meaningful paint
  • Apdex (uses timings to create an index)

Measuring Single page app performance

  • window.onload just doesn't work for SPA's, it's not triggered for subsequent page loads, or at the right time
  • Above-the-fold render time doesn't work for real traffic, but it does give a good impression with simulated traffic.
  • "Apdex" is not easy to compare (with different t values), and does not define what a "satisfactory" page load is.
  • There is no such thing as "load time" as a single number. We want to represent a much richer picture.
    • We represent many different experiences (cold page load, warm page load)
    • We represent many different environments (network conditions, geographical location)
    • However, we need to reduce it to a single number for KPI's, OKR's, etc.
    • We want to compare fairly with other applications

First "meaningful" paint

First meaningful paint provides a good way of measuring user experience, but requires knowledge of what "meaningful" is.

We also still need a good way to measure load times across "warm" page loads, as the first paint isn't the only one!

⏰ react-component-timing

React component timing is a tool that helps you get the above data, so that when you try to move the needle, you actually move it for your users.

  • It lets you define what a meaningful paint is for a React app
  • It breaks down timings by component, so that you can see how your app progressively loads.
  • It provides timings via the User timing API that are easily comparible across different experiences.
  • It provides a pluggable layer that fits into your existing tools: New Relic, Google Analytics, etc.

API

import*asReactfrom"react";import{ReactComponentTimingProvider}from"react-component-timing";import{newRelicIntegration}from"./new-relic-timing-reporter";importwithDatafrom"./app-data-provider";exportclassAppImplextendsReact.Component{checkLoaded({ childTimings }){/* We have access to the timings of all of the children, through some magic */return(childTimings.nav.loaded&&childTimings.article.loaded&&this.props.data.loaded);}render(){return(<ReactComponentTimingProviderreporter={newRelicIntegration}><Page><ReactComponentTimingcomponentName="page"checkLoaded={this.checkLoaded}><Nav/><Content><Article/><Comments/></Content></ReactComponentTiming></Page></ReactComponentTimingProvider>);}}exportconstApp=withData(AppImpl);
import*asReactfrom"react";import{ReactCompomnentTiming}from"react-component-timing";import{NavigationInner}from"./navigation-inner";importwithDatafrom"./nav-data-provider";classNavImplextendsReact.Component{checkLoaded(){returnthis.props.data.loaded;}render(){return(<><ReactCompomnentTimingcomponentName="nav"checkLoaded={this.checkLoaded}/><NavigationInner/></>);}}exportconstNav=withData(NavImpl);

(And similar for Comments and Article, which would both include dynamically loaded data)

API Concepts

Events

  • Load: a component transitioned from "isLoading: false" -> true -> false. The time taken between falses is reported as a "load" event
    • Metadata:
      • Props given to the component during the transition
      • Page path
  • Render: a component entered a render state

How it would work

✨ Through some wizardry and probably some API changes from the above, I think it'd be possible to implement something that would build a picture of the timing of when these "timing" components got rendered, and when they reported that they were loaded.

When props change (and are rerendered), a component can go into and out of a loading state. This loading state, and the reasons why, would be captured by the reporter.

This would let you define custom metrics, for, say, the comments component. You would be able to know a performance timing from cold page load to the comments being loaded, and how that is different on subsequent warm page loads.

The API also allows you to define "loading" states by composing your child loading states (possibly excluding some if they do not constitute "meaningful" for the parent component).


Additional reading

Goals for performance

For what targets to hit, the rail guideline provides good information.

  • Focus on the user.
  • Respond to user input in under 100ms.
  • Produce a frame in under 10ms when animating or scrolling.
  • Maximize main thread idle time.
  • Load interactive content in under 5000ms.

The RAIL framework: _ Response _ Animation _ Idle _ Load

This tool will help measure the Load and Response parts of this framework.

About

Monitor performance at a per component level

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

react-component-performance

Monitor performance at a per component level

Current state is RFC 📄

If you like this idea, or have know of something like this that already exists, or have feedback before I start making anything, let me know!

Motivation for this tool

We want to measure the load time of our apps in a way that,

  • Meaningfully reflects real user experiences, including geography, devices, network conditions
  • Works for single page applications that progressively load parts of the app ("cold" vs. "warm" page loads)
  • Is easily comparible between applications

There are a number of performance metrics that already exist

Ways of measuring performance

  • window.onload timing
  • Above-the-fold render time (ATF)
    • Measurable with webpagetest.org
  • Time to first paint
  • Time to first contentful paint
  • Time to first meaningful paint
  • Apdex (uses timings to create an index)

Measuring Single page app performance

  • window.onload just doesn't work for SPA's, it's not triggered for subsequent page loads, or at the right time
  • Above-the-fold render time doesn't work for real traffic, but it does give a good impression with simulated traffic.
  • "Apdex" is not easy to compare (with different t values), and does not define what a "satisfactory" page load is.
  • There is no such thing as "load time" as a single number. We want to represent a much richer picture.
    • We represent many different experiences (cold page load, warm page load)
    • We represent many different environments (network conditions, geographical location)
    • However, we need to reduce it to a single number for KPI's, OKR's, etc.
    • We want to compare fairly with other applications

First "meaningful" paint

First meaningful paint provides a good way of measuring user experience, but requires knowledge of what "meaningful" is.

We also still need a good way to measure load times across "warm" page loads, as the first paint isn't the only one!

⏰ react-component-timing

React component timing is a tool that helps you get the above data, so that when you try to move the needle, you actually move it for your users.

  • It lets you define what a meaningful paint is for a React app
  • It breaks down timings by component, so that you can see how your app progressively loads.
  • It provides timings via the User timing API that are easily comparible across different experiences.
  • It provides a pluggable layer that fits into your existing tools: New Relic, Google Analytics, etc.

API

import*asReactfrom"react";import{ReactComponentTimingProvider}from"react-component-timing";import{newRelicIntegration}from"./new-relic-timing-reporter";importwithDatafrom"./app-data-provider";exportclassAppImplextendsReact.Component{checkLoaded({ childTimings }){/* We have access to the timings of all of the children, through some magic */return(childTimings.nav.loaded&&childTimings.article.loaded&&this.props.data.loaded);}render(){return(<ReactComponentTimingProviderreporter={newRelicIntegration}><Page><ReactComponentTimingcomponentName="page"checkLoaded={this.checkLoaded}><Nav/><Content><Article/><Comments/></Content></ReactComponentTiming></Page></ReactComponentTimingProvider>);}}exportconstApp=withData(AppImpl);
import*asReactfrom"react";import{ReactCompomnentTiming}from"react-component-timing";import{NavigationInner}from"./navigation-inner";importwithDatafrom"./nav-data-provider";classNavImplextendsReact.Component{checkLoaded(){returnthis.props.data.loaded;}render(){return(<><ReactCompomnentTimingcomponentName="nav"checkLoaded={this.checkLoaded}/><NavigationInner/></>);}}exportconstNav=withData(NavImpl);

(And similar for Comments and Article, which would both include dynamically loaded data)

API Concepts

Events

  • Load: a component transitioned from "isLoading: false" -> true -> false. The time taken between falses is reported as a "load" event
    • Metadata:
      • Props given to the component during the transition
      • Page path
  • Render: a component entered a render state

How it would work

✨ Through some wizardry and probably some API changes from the above, I think it'd be possible to implement something that would build a picture of the timing of when these "timing" components got rendered, and when they reported that they were loaded.

When props change (and are rerendered), a component can go into and out of a loading state. This loading state, and the reasons why, would be captured by the reporter.

This would let you define custom metrics, for, say, the comments component. You would be able to know a performance timing from cold page load to the comments being loaded, and how that is different on subsequent warm page loads.

The API also allows you to define "loading" states by composing your child loading states (possibly excluding some if they do not constitute "meaningful" for the parent component).


Additional reading

Goals for performance

For what targets to hit, the rail guideline provides good information.

  • Focus on the user.
  • Respond to user input in under 100ms.
  • Produce a frame in under 10ms when animating or scrolling.
  • Maximize main thread idle time.
  • Load interactive content in under 5000ms.

The RAIL framework: _ Response _ Animation _ Idle _ Load

This tool will help measure the Load and Response parts of this framework.

About

Monitor performance at a per component level

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

react-component-performance

Monitor performance at a per component level

Current state is RFC 📄

If you like this idea, or have know of something like this that already exists, or have feedback before I start making anything, let me know!

Motivation for this tool

We want to measure the load time of our apps in a way that,

  • Meaningfully reflects real user experiences, including geography, devices, network conditions
  • Works for single page applications that progressively load parts of the app ("cold" vs. "warm" page loads)
  • Is easily comparible between applications

There are a number of performance metrics that already exist

Ways of measuring performance

  • window.onload timing
  • Above-the-fold render time (ATF)
    • Measurable with webpagetest.org
  • Time to first paint
  • Time to first contentful paint
  • Time to first meaningful paint
  • Apdex (uses timings to create an index)

Measuring Single page app performance

  • window.onload just doesn't work for SPA's, it's not triggered for subsequent page loads, or at the right time
  • Above-the-fold render time doesn't work for real traffic, but it does give a good impression with simulated traffic.
  • "Apdex" is not easy to compare (with different t values), and does not define what a "satisfactory" page load is.
  • There is no such thing as "load time" as a single number. We want to represent a much richer picture.
    • We represent many different experiences (cold page load, warm page load)
    • We represent many different environments (network conditions, geographical location)
    • However, we need to reduce it to a single number for KPI's, OKR's, etc.
    • We want to compare fairly with other applications

First "meaningful" paint

First meaningful paint provides a good way of measuring user experience, but requires knowledge of what "meaningful" is.

We also still need a good way to measure load times across "warm" page loads, as the first paint isn't the only one!

⏰ react-component-timing

React component timing is a tool that helps you get the above data, so that when you try to move the needle, you actually move it for your users.

  • It lets you define what a meaningful paint is for a React app
  • It breaks down timings by component, so that you can see how your app progressively loads.
  • It provides timings via the User timing API that are easily comparible across different experiences.
  • It provides a pluggable layer that fits into your existing tools: New Relic, Google Analytics, etc.

API

import*asReactfrom"react";import{ReactComponentTimingProvider}from"react-component-timing";import{newRelicIntegration}from"./new-relic-timing-reporter";importwithDatafrom"./app-data-provider";exportclassAppImplextendsReact.Component{checkLoaded({ childTimings }){/* We have access to the timings of all of the children, through some magic */return(childTimings.nav.loaded&&childTimings.article.loaded&&this.props.data.loaded);}render(){return(<ReactComponentTimingProviderreporter={newRelicIntegration}><Page><ReactComponentTimingcomponentName="page"checkLoaded={this.checkLoaded}><Nav/><Content><Article/><Comments/></Content></ReactComponentTiming></Page></ReactComponentTimingProvider>);}}exportconstApp=withData(AppImpl);
import*asReactfrom"react";import{ReactCompomnentTiming}from"react-component-timing";import{NavigationInner}from"./navigation-inner";importwithDatafrom"./nav-data-provider";classNavImplextendsReact.Component{checkLoaded(){returnthis.props.data.loaded;}render(){return(<><ReactCompomnentTimingcomponentName="nav"checkLoaded={this.checkLoaded}/><NavigationInner/></>);}}exportconstNav=withData(NavImpl);

(And similar for Comments and Article, which would both include dynamically loaded data)

API Concepts

Events

  • Load: a component transitioned from "isLoading: false" -> true -> false. The time taken between falses is reported as a "load" event
    • Metadata:
      • Props given to the component during the transition
      • Page path
  • Render: a component entered a render state

How it would work

✨ Through some wizardry and probably some API changes from the above, I think it'd be possible to implement something that would build a picture of the timing of when these "timing" components got rendered, and when they reported that they were loaded.

When props change (and are rerendered), a component can go into and out of a loading state. This loading state, and the reasons why, would be captured by the reporter.

This would let you define custom metrics, for, say, the comments component. You would be able to know a performance timing from cold page load to the comments being loaded, and how that is different on subsequent warm page loads.

The API also allows you to define "loading" states by composing your child loading states (possibly excluding some if they do not constitute "meaningful" for the parent component).


Additional reading

Goals for performance

For what targets to hit, the rail guideline provides good information.

  • Focus on the user.
  • Respond to user input in under 100ms.
  • Produce a frame in under 10ms when animating or scrolling.
  • Maximize main thread idle time.
  • Load interactive content in under 5000ms.

The RAIL framework: _ Response _ Animation _ Idle _ Load

This tool will help measure the Load and Response parts of this framework.

About

Monitor performance at a per component level

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

react-component-performance

Monitor performance at a per component level

Current state is RFC 📄

If you like this idea, or have know of something like this that already exists, or have feedback before I start making anything, let me know!

Motivation for this tool

We want to measure the load time of our apps in a way that,

  • Meaningfully reflects real user experiences, including geography, devices, network conditions
  • Works for single page applications that progressively load parts of the app ("cold" vs. "warm" page loads)
  • Is easily comparible between applications

There are a number of performance metrics that already exist

Ways of measuring performance

  • window.onload timing
  • Above-the-fold render time (ATF)
    • Measurable with webpagetest.org
  • Time to first paint
  • Time to first contentful paint
  • Time to first meaningful paint
  • Apdex (uses timings to create an index)

Measuring Single page app performance

  • window.onload just doesn't work for SPA's, it's not triggered for subsequent page loads, or at the right time
  • Above-the-fold render time doesn't work for real traffic, but it does give a good impression with simulated traffic.
  • "Apdex" is not easy to compare (with different t values), and does not define what a "satisfactory" page load is.
  • There is no such thing as "load time" as a single number. We want to represent a much richer picture.
    • We represent many different experiences (cold page load, warm page load)
    • We represent many different environments (network conditions, geographical location)
    • However, we need to reduce it to a single number for KPI's, OKR's, etc.
    • We want to compare fairly with other applications

First "meaningful" paint

First meaningful paint provides a good way of measuring user experience, but requires knowledge of what "meaningful" is.

We also still need a good way to measure load times across "warm" page loads, as the first paint isn't the only one!

⏰ react-component-timing

React component timing is a tool that helps you get the above data, so that when you try to move the needle, you actually move it for your users.

  • It lets you define what a meaningful paint is for a React app
  • It breaks down timings by component, so that you can see how your app progressively loads.
  • It provides timings via the User timing API that are easily comparible across different experiences.
  • It provides a pluggable layer that fits into your existing tools: New Relic, Google Analytics, etc.

API

import*asReactfrom"react";import{ReactComponentTimingProvider}from"react-component-timing";import{newRelicIntegration}from"./new-relic-timing-reporter";importwithDatafrom"./app-data-provider";exportclassAppImplextendsReact.Component{checkLoaded({ childTimings }){/* We have access to the timings of all of the children, through some magic */return(childTimings.nav.loaded&&childTimings.article.loaded&&this.props.data.loaded);}render(){return(<ReactComponentTimingProviderreporter={newRelicIntegration}><Page><ReactComponentTimingcomponentName="page"checkLoaded={this.checkLoaded}><Nav/><Content><Article/><Comments/></Content></ReactComponentTiming></Page></ReactComponentTimingProvider>);}}exportconstApp=withData(AppImpl);
import*asReactfrom"react";import{ReactCompomnentTiming}from"react-component-timing";import{NavigationInner}from"./navigation-inner";importwithDatafrom"./nav-data-provider";classNavImplextendsReact.Component{checkLoaded(){returnthis.props.data.loaded;}render(){return(<><ReactCompomnentTimingcomponentName="nav"checkLoaded={this.checkLoaded}/><NavigationInner/></>);}}exportconstNav=withData(NavImpl);

(And similar for Comments and Article, which would both include dynamically loaded data)

API Concepts

Events

  • Load: a component transitioned from "isLoading: false" -> true -> false. The time taken between falses is reported as a "load" event
    • Metadata:
      • Props given to the component during the transition
      • Page path
  • Render: a component entered a render state

How it would work

✨ Through some wizardry and probably some API changes from the above, I think it'd be possible to implement something that would build a picture of the timing of when these "timing" components got rendered, and when they reported that they were loaded.

When props change (and are rerendered), a component can go into and out of a loading state. This loading state, and the reasons why, would be captured by the reporter.

This would let you define custom metrics, for, say, the comments component. You would be able to know a performance timing from cold page load to the comments being loaded, and how that is different on subsequent warm page loads.

The API also allows you to define "loading" states by composing your child loading states (possibly excluding some if they do not constitute "meaningful" for the parent component).


Additional reading

Goals for performance

For what targets to hit, the rail guideline provides good information.

  • Focus on the user.
  • Respond to user input in under 100ms.
  • Produce a frame in under 10ms when animating or scrolling.
  • Maximize main thread idle time.
  • Load interactive content in under 5000ms.

The RAIL framework: _ Response _ Animation _ Idle _ Load

This tool will help measure the Load and Response parts of this framework.

About

Monitor performance at a per component level

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

react-component-performance

Monitor performance at a per component level

Current state is RFC 📄

If you like this idea, or have know of something like this that already exists, or have feedback before I start making anything, let me know!

Motivation for this tool

We want to measure the load time of our apps in a way that,

  • Meaningfully reflects real user experiences, including geography, devices, network conditions
  • Works for single page applications that progressively load parts of the app ("cold" vs. "warm" page loads)
  • Is easily comparible between applications

There are a number of performance metrics that already exist

Ways of measuring performance

  • window.onload timing
  • Above-the-fold render time (ATF)
    • Measurable with webpagetest.org
  • Time to first paint
  • Time to first contentful paint
  • Time to first meaningful paint
  • Apdex (uses timings to create an index)

Measuring Single page app performance

  • window.onload just doesn't work for SPA's, it's not triggered for subsequent page loads, or at the right time
  • Above-the-fold render time doesn't work for real traffic, but it does give a good impression with simulated traffic.
  • "Apdex" is not easy to compare (with different t values), and does not define what a "satisfactory" page load is.
  • There is no such thing as "load time" as a single number. We want to represent a much richer picture.
    • We represent many different experiences (cold page load, warm page load)
    • We represent many different environments (network conditions, geographical location)
    • However, we need to reduce it to a single number for KPI's, OKR's, etc.
    • We want to compare fairly with other applications

First "meaningful" paint

First meaningful paint provides a good way of measuring user experience, but requires knowledge of what "meaningful" is.

We also still need a good way to measure load times across "warm" page loads, as the first paint isn't the only one!

⏰ react-component-timing

React component timing is a tool that helps you get the above data, so that when you try to move the needle, you actually move it for your users.

  • It lets you define what a meaningful paint is for a React app
  • It breaks down timings by component, so that you can see how your app progressively loads.
  • It provides timings via the User timing API that are easily comparible across different experiences.
  • It provides a pluggable layer that fits into your existing tools: New Relic, Google Analytics, etc.

API

import*asReactfrom"react";import{ReactComponentTimingProvider}from"react-component-timing";import{newRelicIntegration}from"./new-relic-timing-reporter";importwithDatafrom"./app-data-provider";exportclassAppImplextendsReact.Component{checkLoaded({ childTimings }){/* We have access to the timings of all of the children, through some magic */return(childTimings.nav.loaded&&childTimings.article.loaded&&this.props.data.loaded);}render(){return(<ReactComponentTimingProviderreporter={newRelicIntegration}><Page><ReactComponentTimingcomponentName="page"checkLoaded={this.checkLoaded}><Nav/><Content><Article/><Comments/></Content></ReactComponentTiming></Page></ReactComponentTimingProvider>);}}exportconstApp=withData(AppImpl);
import*asReactfrom"react";import{ReactCompomnentTiming}from"react-component-timing";import{NavigationInner}from"./navigation-inner";importwithDatafrom"./nav-data-provider";classNavImplextendsReact.Component{checkLoaded(){returnthis.props.data.loaded;}render(){return(<><ReactCompomnentTimingcomponentName="nav"checkLoaded={this.checkLoaded}/><NavigationInner/></>);}}exportconstNav=withData(NavImpl);

(And similar for Comments and Article, which would both include dynamically loaded data)

API Concepts

Events

  • Load: a component transitioned from "isLoading: false" -> true -> false. The time taken between falses is reported as a "load" event
    • Metadata:
      • Props given to the component during the transition
      • Page path
  • Render: a component entered a render state

How it would work

✨ Through some wizardry and probably some API changes from the above, I think it'd be possible to implement something that would build a picture of the timing of when these "timing" components got rendered, and when they reported that they were loaded.

When props change (and are rerendered), a component can go into and out of a loading state. This loading state, and the reasons why, would be captured by the reporter.

This would let you define custom metrics, for, say, the comments component. You would be able to know a performance timing from cold page load to the comments being loaded, and how that is different on subsequent warm page loads.

The API also allows you to define "loading" states by composing your child loading states (possibly excluding some if they do not constitute "meaningful" for the parent component).


Additional reading

Goals for performance

For what targets to hit, the rail guideline provides good information.

  • Focus on the user.
  • Respond to user input in under 100ms.
  • Produce a frame in under 10ms when animating or scrolling.
  • Maximize main thread idle time.
  • Load interactive content in under 5000ms.

The RAIL framework: _ Response _ Animation _ Idle _ Load

This tool will help measure the Load and Response parts of this framework.

About

Monitor performance at a per component level

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

react-component-performance

Monitor performance at a per component level

Current state is RFC 📄

If you like this idea, or have know of something like this that already exists, or have feedback before I start making anything, let me know!

Motivation for this tool

We want to measure the load time of our apps in a way that,

  • Meaningfully reflects real user experiences, including geography, devices, network conditions
  • Works for single page applications that progressively load parts of the app ("cold" vs. "warm" page loads)
  • Is easily comparible between applications

There are a number of performance metrics that already exist

Ways of measuring performance

  • window.onload timing
  • Above-the-fold render time (ATF)
    • Measurable with webpagetest.org
  • Time to first paint
  • Time to first contentful paint
  • Time to first meaningful paint
  • Apdex (uses timings to create an index)

Measuring Single page app performance

  • window.onload just doesn't work for SPA's, it's not triggered for subsequent page loads, or at the right time
  • Above-the-fold render time doesn't work for real traffic, but it does give a good impression with simulated traffic.
  • "Apdex" is not easy to compare (with different t values), and does not define what a "satisfactory" page load is.
  • There is no such thing as "load time" as a single number. We want to represent a much richer picture.
    • We represent many different experiences (cold page load, warm page load)
    • We represent many different environments (network conditions, geographical location)
    • However, we need to reduce it to a single number for KPI's, OKR's, etc.
    • We want to compare fairly with other applications

First "meaningful" paint

First meaningful paint provides a good way of measuring user experience, but requires knowledge of what "meaningful" is.

We also still need a good way to measure load times across "warm" page loads, as the first paint isn't the only one!

⏰ react-component-timing

React component timing is a tool that helps you get the above data, so that when you try to move the needle, you actually move it for your users.

  • It lets you define what a meaningful paint is for a React app
  • It breaks down timings by component, so that you can see how your app progressively loads.
  • It provides timings via the User timing API that are easily comparible across different experiences.
  • It provides a pluggable layer that fits into your existing tools: New Relic, Google Analytics, etc.

API

import*asReactfrom"react";import{ReactComponentTimingProvider}from"react-component-timing";import{newRelicIntegration}from"./new-relic-timing-reporter";importwithDatafrom"./app-data-provider";exportclassAppImplextendsReact.Component{checkLoaded({ childTimings }){/* We have access to the timings of all of the children, through some magic */return(childTimings.nav.loaded&&childTimings.article.loaded&&this.props.data.loaded);}render(){return(<ReactComponentTimingProviderreporter={newRelicIntegration}><Page><ReactComponentTimingcomponentName="page"checkLoaded={this.checkLoaded}><Nav/><Content><Article/><Comments/></Content></ReactComponentTiming></Page></ReactComponentTimingProvider>);}}exportconstApp=withData(AppImpl);
import*asReactfrom"react";import{ReactCompomnentTiming}from"react-component-timing";import{NavigationInner}from"./navigation-inner";importwithDatafrom"./nav-data-provider";classNavImplextendsReact.Component{checkLoaded(){returnthis.props.data.loaded;}render(){return(<><ReactCompomnentTimingcomponentName="nav"checkLoaded={this.checkLoaded}/><NavigationInner/></>);}}exportconstNav=withData(NavImpl);

(And similar for Comments and Article, which would both include dynamically loaded data)

API Concepts

Events

  • Load: a component transitioned from "isLoading: false" -> true -> false. The time taken between falses is reported as a "load" event
    • Metadata:
      • Props given to the component during the transition
      • Page path
  • Render: a component entered a render state

How it would work

✨ Through some wizardry and probably some API changes from the above, I think it'd be possible to implement something that would build a picture of the timing of when these "timing" components got rendered, and when they reported that they were loaded.

When props change (and are rerendered), a component can go into and out of a loading state. This loading state, and the reasons why, would be captured by the reporter.

This would let you define custom metrics, for, say, the comments component. You would be able to know a performance timing from cold page load to the comments being loaded, and how that is different on subsequent warm page loads.

The API also allows you to define "loading" states by composing your child loading states (possibly excluding some if they do not constitute "meaningful" for the parent component).


Additional reading

Goals for performance

For what targets to hit, the rail guideline provides good information.

  • Focus on the user.
  • Respond to user input in under 100ms.
  • Produce a frame in under 10ms when animating or scrolling.
  • Maximize main thread idle time.
  • Load interactive content in under 5000ms.

The RAIL framework: _ Response _ Animation _ Idle _ Load

This tool will help measure the Load and Response parts of this framework.

About

Monitor performance at a per component level

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

react-component-performance

Monitor performance at a per component level

Current state is RFC 📄

If you like this idea, or have know of something like this that already exists, or have feedback before I start making anything, let me know!

Motivation for this tool

We want to measure the load time of our apps in a way that,

  • Meaningfully reflects real user experiences, including geography, devices, network conditions
  • Works for single page applications that progressively load parts of the app ("cold" vs. "warm" page loads)
  • Is easily comparible between applications

There are a number of performance metrics that already exist

Ways of measuring performance

  • window.onload timing
  • Above-the-fold render time (ATF)
    • Measurable with webpagetest.org
  • Time to first paint
  • Time to first contentful paint
  • Time to first meaningful paint
  • Apdex (uses timings to create an index)

Measuring Single page app performance

  • window.onload just doesn't work for SPA's, it's not triggered for subsequent page loads, or at the right time
  • Above-the-fold render time doesn't work for real traffic, but it does give a good impression with simulated traffic.
  • "Apdex" is not easy to compare (with different t values), and does not define what a "satisfactory" page load is.
  • There is no such thing as "load time" as a single number. We want to represent a much richer picture.
    • We represent many different experiences (cold page load, warm page load)
    • We represent many different environments (network conditions, geographical location)
    • However, we need to reduce it to a single number for KPI's, OKR's, etc.
    • We want to compare fairly with other applications

First "meaningful" paint

First meaningful paint provides a good way of measuring user experience, but requires knowledge of what "meaningful" is.

We also still need a good way to measure load times across "warm" page loads, as the first paint isn't the only one!

⏰ react-component-timing

React component timing is a tool that helps you get the above data, so that when you try to move the needle, you actually move it for your users.

  • It lets you define what a meaningful paint is for a React app
  • It breaks down timings by component, so that you can see how your app progressively loads.
  • It provides timings via the User timing API that are easily comparible across different experiences.
  • It provides a pluggable layer that fits into your existing tools: New Relic, Google Analytics, etc.

API

import*asReactfrom"react";import{ReactComponentTimingProvider}from"react-component-timing";import{newRelicIntegration}from"./new-relic-timing-reporter";importwithDatafrom"./app-data-provider";exportclassAppImplextendsReact.Component{checkLoaded({ childTimings }){/* We have access to the timings of all of the children, through some magic */return(childTimings.nav.loaded&&childTimings.article.loaded&&this.props.data.loaded);}render(){return(<ReactComponentTimingProviderreporter={newRelicIntegration}><Page><ReactComponentTimingcomponentName="page"checkLoaded={this.checkLoaded}><Nav/><Content><Article/><Comments/></Content></ReactComponentTiming></Page></ReactComponentTimingProvider>);}}exportconstApp=withData(AppImpl);
import*asReactfrom"react";import{ReactCompomnentTiming}from"react-component-timing";import{NavigationInner}from"./navigation-inner";importwithDatafrom"./nav-data-provider";classNavImplextendsReact.Component{checkLoaded(){returnthis.props.data.loaded;}render(){return(<><ReactCompomnentTimingcomponentName="nav"checkLoaded={this.checkLoaded}/><NavigationInner/></>);}}exportconstNav=withData(NavImpl);

(And similar for Comments and Article, which would both include dynamically loaded data)

API Concepts

Events

  • Load: a component transitioned from "isLoading: false" -> true -> false. The time taken between falses is reported as a "load" event
    • Metadata:
      • Props given to the component during the transition
      • Page path
  • Render: a component entered a render state

How it would work

✨ Through some wizardry and probably some API changes from the above, I think it'd be possible to implement something that would build a picture of the timing of when these "timing" components got rendered, and when they reported that they were loaded.

When props change (and are rerendered), a component can go into and out of a loading state. This loading state, and the reasons why, would be captured by the reporter.

This would let you define custom metrics, for, say, the comments component. You would be able to know a performance timing from cold page load to the comments being loaded, and how that is different on subsequent warm page loads.

The API also allows you to define "loading" states by composing your child loading states (possibly excluding some if they do not constitute "meaningful" for the parent component).


Additional reading

Goals for performance

For what targets to hit, the rail guideline provides good information.

  • Focus on the user.
  • Respond to user input in under 100ms.
  • Produce a frame in under 10ms when animating or scrolling.
  • Maximize main thread idle time.
  • Load interactive content in under 5000ms.

The RAIL framework: _ Response _ Animation _ Idle _ Load

This tool will help measure the Load and Response parts of this framework.

About

Monitor performance at a per component level

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages