惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cloudbric
Cloudbric
T
Threat Research - Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
AWS News Blog
AWS News Blog
P
Privacy & Cybersecurity Law Blog
H
Help Net Security
云风的 BLOG
云风的 BLOG
G
GRAHAM CLULEY
Spread Privacy
Spread Privacy
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
A
Arctic Wolf
Project Zero
Project Zero
Engineering at Meta
Engineering at Meta
P
Privacy International News Feed
Blog — PlanetScale
Blog — PlanetScale
Stack Overflow Blog
Stack Overflow Blog
M
MIT News - Artificial intelligence
The Register - Security
The Register - Security
Recorded Future
Recorded Future
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Cisco Blogs
PCI Perspectives
PCI Perspectives
Recent Announcements
Recent Announcements
Martin Fowler
Martin Fowler
A
About on SuperTechFans
W
WeLiveSecurity
GbyAI
GbyAI
V
Vulnerabilities – Threatpost
The GitHub Blog
The GitHub Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Check Point Blog
Y
Y Combinator Blog
月光博客
月光博客
Scott Helme
Scott Helme
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google DeepMind News
Google DeepMind News
F
Fortinet All Blogs
U
Unit 42
G
Google Developers Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Threatpost
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google Online Security Blog
Google Online Security Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cisco Talos Blog
Cisco Talos Blog
博客园 - 三生石上(FineUI控件)
Hugging Face - Blog
Hugging Face - Blog
MongoDB | Blog
MongoDB | Blog
博客园 - 司徒正美

remy sharp's l:inks

Deno Style Guide Easy 6502 by skilldrick BEM Naming Cheat Sheet by 9elements Visual 6502 Remix Elijah Manor (@elijahmanor) on X All – Tiny Helpers AST explorer Insecure How to Authenticate with Next.js and Auth0: A Guide for Every Deployment Model Revealed: quarter of all tweets about climate crisis produced by bots I Add 3-25 Seconds of Latency to Every Page I Visit GitHub - ericchiang/pup: Parsing HTML at the command line Browserling – Online cross-browser testing Error Handling with GraphQL and Apollo Schwerkraftprojektionsgerät How To Turn Off Catalina Update Notifications (Prompts & Badges) • macReports Maskable.app It’s 2020 and you’re in the future Emulators written in JavaScript | Frederic Cambus The Size of Space systemfontstack JavaScript isn’t always available and it’s not the user’s fault Programming Fonts - Test Drive Screen Size Map GitHub - Yonet/MixedRealityResources: Mixed Reality related resources The Lines of Code That Changed Everything Notes from the Internet Health Report 2019 CopyPalette Generative Artistry Profile a React App for Performance nanoSQL 2 Moving Your JavaScript Development To Bash On Windows — Smashing Magazine Startup Playbook How to Release a Custom React Component, Hook or Effect as an npm Package React Suite - Enterprise React UI Component Library Use VSCode Dimmer to Highlight Code when Teaching 3 simple rules for effectively handling dates and timezones Large collection of how to animate pixelart Accessible React component libraries mineral-ui.com Australian Government Design System Reakit – Toolkit for building accessible UIs Chakra UI Curl Cookbook The problem with tooltips and what to do instead GitHub - trimstray/the-book-of-secret-knowledge: A collection of inspiring lists, manuals, cheatsheets, blogs, hacks, one-liners, cli/web tools and more. It Form design: from zero to hero all in one blog post Brussels changes its mind AGAIN on .EU domains: Euro citizens in post-Brexit Britain can keep them after all Improve Your Email Campaigns with These Fantastic Tools Ethical Web Principles Old Typewriter Text Effect Bruce Lawson Google open sources standardized code in bid to become Mr Robots.txt Preferreds-color-scheme:你好,黑暗,我的老朋友  |  Articles  |  web.dev Free for Developers Startup idea checklist Developing a Robust Font Loading Strategy for CSS-Tricks—zachleat.com How I use Slack—alone—to get more done Upcoming proposals in JavaScript 🦄 VueJS is dead, long live VueJS! Bruce Lawson Answers for young people - Tim Berners-Lee Finally, an AI that can reliably catch and undo Photoshop airbrushing. Who made it? Er, Photoshop maker Adobe Qubyte Codes - How I schedule posts using GitHub Actions Games and Graphics in Popup URL bars Stack 58 bytes of css to look great nearly everywhere The reduce ({...spread}) anti-pattern - RichSnapp.com The Online Disassembler CSS Gradient – Generator, Maker, and Background Chrome DevTools  |  Chrome for Developers HB88 | Đăng Nhập HB88 Cá Cược Nhanh Chóng Không Bị Chăn #1 Introducing React Apollo 2.1 - Apollo GraphQL Blog Color Palettes Generator and Color Gradient Tool Clément Chastagnol ~ Moving efficiently in the CLI Testing Async Components · Issue #346 · enzymejs/enzyme Game Platforms recent news | Game Developer Professional Sound Effects - Royalty-Free SFX | Unlimited Downloads entr(1) Learn React From The Comfort Of Your Browser Axe Rules | Deque University Record and share your terminal sessions, the simple way Web Design Museum Powerful New Additions to the CSS Grid Inspector in Firefox Nightly – Mozilla Hacks - the Web developer blog Latency | Apex Software HackerNoon Signals and Sine Waves (Learn Web Audio from the Ground Up, Part 1) JavaScript Systems Music Vintage bits on cassettes Microsoft Design Legal Documents & Contract Templates | Simply Docs create-graphql-server — instantly scaffold a GraphQL server GraphQL and MongoDB — a quick example Using GraphQL with MongoDB Your First GraphQL Server Build a GraphQL server from scratch Practical Redux, Part 3: Project Planning and Setup 架构标记测试工具 | Google 搜索中心  |  Search Central  |  Google for Developers Freesound
Profiling React.js Performance
Addy Osmani · 2020-05-03 · via remy sharp's l:inks

Today, we’ll look at measuring React component render performance with the React Profiler API, measuring interactions with React’s new experimental Interaction Tracing API and measuring custom metrics using the User Timing API.

For demonstration purposes, we’ll be using a Movie queueing app.

The React Profiler API

The React Profiler API measures renders and the cost of rendering to help identify slow bottlenecks in applications.

import React, { Fragment, unstable_Profiler as Profiler} from "react";

The Profiler takes an onRender callback as a prop that is called any time a component in the tree being profiled commits an update.

const Movies = ({ movies, addToQueue }) => (
  <Fragment>
    <Profiler id="Movies" onRender={callback}>

For testing purposes, let’s try measuring the rendering time of parts of a Movies component with the Profiler. It’s this:

React Movies Queue with the React DevTools inspecting movies

The Profiler’s onRender callback accepts parameters that describe what was rendered and the length of time it took. These include:

  • id: The “id” prop of the Profiler tree that just committed
  • phase: “mount” (if tree mounted) or “update” (if re-rendered)
  • actualDuration: time rendering the committed update
  • baseDuration: estimated time to render full subtree without memoization
  • startTime: time when Reach began rendering the update
  • commitTime: time when React committed the update
  • interactions: interactions belonging to the update
const callback = (id, phase, actualTime, baseTime, startTime, commitTime) => {
    console.log(`${id}'s ${phase} phase:`);
    console.log(`Actual time: ${actualTime}`);
    console.log(`Base time: ${baseTime}`);
    console.log(`Start time: ${startTime}`);
    console.log(`Commit time: ${commitTime}`);
}

We can load our page, head over to the Chrome DevTools console and should see the following timings:

Profiler times in DevTools

We can also open the React DevTools, go to the Profiler tab and visualize our component Rendering times. Below is the Flame-graph view:

React DevTools showing profiler api

I also enjoy using Ranked view, which is ordered so components taking the longest to render are shown at the top:

Ranked view in React DevTools

It’s also possible to use multiple Profilers for measuring different parts of your application:

import React, { Fragment, unstable_Profiler as Profiler} from "react";

render(
  <App>
    <Profiler id="Header" onRender={callback}>
      <Header {...props} />
    </Profiler>
    <Profiler id="Movies" onRender={callback}>
      <Movies {...props} />
    </Profiler>
  </App>
);

But, what if you want interaction tracing?

The Interaction Tracing API

It would be powerful if we could trace interactions (e.g clicking UI) to answer questions like “How long did this button click take to update the DOM?”. Thanks to Brian Vaughn, React has experimental support for interaction tracing via the interaction tracing API in the new scheduler package. It is documented in more detail here.

Interactions are annotated with a description (e.g “Add To Cart button clicked”) and a timestamp. Interactions should also be provided a callback where you can do work related to the interaction.

In our Movies application, we have an “Add Movie To Queue” button (“+”). Clicking this interaction adds the movie to your watch queue:

Add movie to queue

Below is an example of tracing state updates for this interaction:

import { unstable_Profiler as Profiler } from "react";
import { render } from "react-dom";
import { unstable_trace as trace } from "scheduler/tracing";

class MyComponent extends Component {
  addMovieButtonClick = event => {
    trace("Add To Movies Queue click", performance.now(), () => {
      this.setState({ itemAddedToQueue: true });
    });
  };
}

We can record this interaction and see the duration for it presented in the React DevTools:

It’s also possible to trace initial render using the interaction tracing API, as follows:

import { unstable_trace as trace } from "scheduler/tracing";

trace("initial render", performance.now(), () => {
   ReactDom.render(<App />, document.getElementById("app"));
});

Brian covers a lot more examples, such as how to trace async work, in his interaction tracing with React gist.

Puppeteer

For even deeper scripted tracing of UI interactions, you might be interested in Puppeteer. Puppeteer is a Node library providing a high-level API for controlling headless Chrome over the DevTools protocol.

It exposes tracing.start()/stop() helpers for capturing a DevTools performance trace of work. Below, we use it to trace what happens when you click a primary button.

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  const navigationPromise = page.waitForNavigation();
  await page.goto('https://react-movies-queue.glitch.me/')
  await page.setViewport({ width: 1276, height: 689 });
  await navigationPromise;

  const addMovieToQueueBtn = 'li:nth-child(3) > .card > .card__info > div > .button';
  await page.waitForSelector(addMovieToQueueBtn);

  // Begin profiling...
  await page.tracing.start({ path: 'profile.json' });
  // Click the button
  await page.click(addMovieToQueueBtn);
  // Stop profliling
  await page.tracing.stop();
  
  await browser.close();
})()

Loading profile.json into the DevTools Performance panel, we can see all of the resulting JavaScript function calls from clicking our button:

If you are interested in reading more on this topic, check out JavaScript component-level CPU costs by Stoyan Stefanov.

User Timing API

The User Timing API enables measuring custom performance metrics for applications using high-precision timestamps. window.performance.mark() stores a timestamp with the associated name and window.performance.measure() stores the time elapsed between two marks.

// Record the time before running a task
performance.mark('Movies:updateStart');
// Do some work

// Record the time after running a task
performance.mark('Movies:updateEnd');

// Measure the difference between the start and end of the task
performance.measure('moviesRender', 'Movies:updateStart', 'Movies:updateEnd');

When you profile a React app using the Chrome DevTools Performance panel, you’ll find a section called “Timings” populated with processing time for your React components. While rendering, React is able to publish this info with the User Timing API.

Note: React is removing User Timings from their DEV bundles in favor of React Profiler, which provides more accurate timings. They may re-add it for Level 3 spec browsers in the future.

Across the web, you’ll find otherwise React apps leveraging User Timing to define their own custom metrics. These include Reddit’s “Time to first post title visible” and Spotify’s “Time to playback ready”:

Custom User Timing marks and measures are also conveniently reflected in the Lighthouse panel in Chrome DevTools:

Recent versions of Next.js have also added more user timing marks and measures for a number of events, including:

  • Next.js-hydration: duration of hydration
  • Next.js-nav-to-render: navigation start until right before render

All of these measures appear in the Timings area:

As a reminder, Lighthouse and the Chrome DevTools Performance panel can be used to deeply analyze load and runtime performance of your React app, highlighting key user-centric happiness metrics:

React users may appreciate new metrics like Total Blocking Time (TBT), which quantifies just how non-interactive a page is prior it to becoming reliably interactive (Time to Interactive). Below we can see the a before/after TBT for an app with Concurrent Mode on where updates are better spread out:

These tools are generally helpful for getting a browser-level view of bottlenecks such as heavy Long Tasks that delay interactions (like button click responsiveness), as seen below:

Long Tasks highlighted in the devtools performance panelLighthouse also offers React-specific guidance for a number of audits. Below, in Lighthouse 6.0 you’ll see a remove unused JavaScript audit, highlighting unused onload JavaScript that could be dynamically imported using React.lazy().

It’s always good to sanity-check performance on hardware representative of your real users. I often rely on webpagetest.org/easy and field-data from RUM and CrUX to paint a more complete picture.

Read more

If you’re interested in experimenting with React Profiler on the demo app in this post, the dev demo and source are on Glitch.