这是用户在 2024-3-20 18:38 为 https://github.com/coryhouse/reactjsconsulting/issues/77 保存的双语快照页面,由 沉浸式翻译 提供双语支持。了解如何保存?
Skip to content
You have unread notifications
coryhouse  /   reactjsconsulting  /   Issues #77  /  

Performance Checklist #77
绩效清单 #77

Open
74 tasks
coryhouse opened this issue Nov 5, 2021 · 0 comments
Open
74 tasks

Performance Checklist #77

coryhouse opened this issue Nov 5, 2021 · 0 comments

Comments

@coryhouse
Copy link
Owner

coryhouse commented Nov 5, 2021

42+ ways to make your React app faster ⚛️:
让 React 应用程序更快的 42+ 种方法 ⚛️:

Performance Testing 性能测试

  • Check core web vitals like INP
    检查核心网络生命体征,如 INP
  • Use https://million.dev/lint
    使用 https://million.dev/lint
  • Analyze performance via the React dev tools.
    通过 React 开发工具分析性能。
    • Use React dev tools "Highlight Updates" to see what's re-rendering. Then be strategic.
      使用 React 开发工具 "突出显示更新 "来查看重新渲染的内容。然后采取策略。
      • Ask: why is this component re-rendering?
        问:为什么这个组件要重新渲染?
      • Ask: Could I avoid passing the prop that's causing it to re-render? Could it access this data via Context instead to avoid passing it through intermediate components that don't need it?
        问:我能否避免传递导致重新渲染的道具?是否可以通过 "上下文 "访问这些数据,以避免通过不需要这些数据的中间组件?
    • Enable why each component is rendering.
      启用每个组件渲染的原因。
    • Learn to use the React profiler, and read the flamechart: Yellow = took more time. Blue = took less time. Gray = did not render during this commit. (source)
      学习使用 React 剖析器,并阅读火焰图:黄色 = 花费更多时间。蓝色 = 耗时较少。灰色 = 本次提交期间未渲染。( 源代码)
  • Use console.time like this, against the prod build, to measure slowness and compare to a before and after to determine if useMemo is a net win: console.time('filter array'); const visibleTodos = getFilteredTodos(todos, filter); console.timeEnd('filter array');
    像这样使用 console.time ,与原型构建对比,测量速度慢的程度,并与之前和之后进行比较,以确定 useMemo 是否净赢: console.time('filter array'); const visibleTodos = getFilteredTodos(todos, filter); console.timeEnd('filter array');
  • Use https://github.com/welldone-software/why-did-you-render
    使用 https://github.com/welldone-software/why-did-you-render
  • Use Chrome's CPU and network slowdown features
    使用 Chrome 浏览器的 CPU 和网络减速功能
  • Tip: Store large mock datasets/config objects in JSON. It's parsed 80% faster.
    小贴士以 JSON 格式存储大型模拟数据集/配置对象。解析速度会快 80%。
  • Create/simulate a large dataset/slow component using one of the options below
    使用以下选项之一创建/模拟大型数据集/慢速组件

Generate a simple fake dataset in a loop.
循环生成一个简单的假数据集。

export function generateProducts() {
  const products = [];
  for (let i = 0; i < 10000; i++) {
    products.push(`Product ${i+1}`);
  }
  return products;
}

Generate a large fake dataset using tools like Faker, Chance, etc.
使用 Faker、Chance 等工具生成一个大型假数据集。

import faker from "faker";

export const fakeNames = Array.from(Array(10000), () => {
  return faker.name.findName();
});

Simulate a slow component via a loop:
通过循环模拟慢速分量

function ExpensiveTree() {
  let now = performance.now();
  while (performance.now() - now < 100) {
    // Artificial delay -- do nothing for 100ms
  }
  return <p>I am a very slow component tree.</p>;
}

Forms 表格

HTTP 超文本传输协定

Rendering 

  • Statically render if possible (Easy via Next.js, Gatsby) 
  • Consider server rendering to avoid slow network waterfalls (easy via Remix / Next.js) 
  • Prefetch / render-as-you-fetch (React's "default" is fetch as you render since the render triggers a fetch via useEffect). React-query's prefetching is a simple way to render as you fetch. Remix also does this by default since nested routes declare data dependencies and run in parallel on the server. My tweet on this 
  • If server rendering with Remix, Next, Docusaurus, etc, Enable time-slicing with React.startTransition at the root. This avoids jank if the user scrolls before hydration completes. 
  • Consider using million's block virtual DOM instead if there is a lot of static content with little dynamic content. Million diffs state instead of DOM, which is fast if there's a little state, but a LOT of DOM. 

Context 

Routing 

  • Implement client-side routing via React Router (or you frameworks built-in alternative, such as Next.js) 

Keys 

  • Assure keys are assigned, and stable over time. Their values should not change based on array order or edits to the data. 
  • Reuse keys to avoid needless renders for items that frequently appear/disappear in the viewport. 
  • Consider using the array’s index as key for dynamic lists with stateless items, where items are replaced with the new ones - paginated lists, search and autocomplete results and the like. This will improve the list’s performance because the entire thing doesn't have to re-render. The component instances are reused. Demo and blog post 

State 

  • Keep state as local as possible. Start by declaring state in the component that uses it. Lift as needed. 
  • Store data that doesn't need to render in refs 
  • Consider useReducer over useState so you can pass dispatch down instead of callbacks (avoids needless renders) 
  • Avoid deep cloning. To avoid, only clone the subobjects that have changed. Or perhaps better yet, avoid nesting objects in state since doing so can lead to needless renders. Instead, "flatten" state by creating separate pieces of state. 
  • Use memo, ref, or pass a func to useState if the initial value calls an expensive func, otherwise, it will be calculated on each render. 
  • Use useTransition for low priority updates (reduces jank) - Demo
  • Use useLayoutEffect to avoid a Flash of unstyled content when you need to read and manipulate the DOM before the user sees it - Demo

Memoization / Identity

  • Memoize expensive operations via useMemo
  • Avoid needless renders via React.memo
  • Consider wrapping functions passed to children in useCallback to avoid needless renders in children
  • Prefer pure functions (which can be extracted from the component) over useCallback when possible

Props

  • Pass the minimal amount of data to each component (remember, components re-render when props change)
  • Pass primitives (strings, numbers...) to child components to assist with diffing. Avoid passing arrow funcs and objects on props when performance is a concern since it leads to needless re-renders of child components.
  • useDeferredValue if it's a low priority update and you can't use useTransition because you don't control the value coming in (coming from third party or via a prop you can't control). Another demo

Component composition / Children

  • Put content that renders frequently in a separate component to minimize the amount that's rendered
  • Embrace reusable components. Each reuse of a reusable component is nearly free.
  • Compose higher level components out of lower level components.
  • Create layout components to centralize reusable layout
  • Lift content up - Pass children down (do this before you memo). Why does this work? Because components passed as children don’t re-render since they are just props. Note: don't pass a function as a child, since it'll still re-render because the func will be recreated on each render
  • Declare functions that need not be in the React component outside the component. This way they're not reallocated on every render.
  • Declare static values outside the component so they're not reallocated on every render.

Design

  • Use pagination, sorting, filtering, pages, tabs, accordions, modals, etc to avoid displaying too much data at the same time.
  • Use tools like react-window to handle large lists by only rendering what's currently visible.
  • Consider implementing optimistic updates when the API is slow (immediately update the UI even though the API call is still in progress behind the scenes)

Bundle optimization

Third party libraries

  • Avoid named imports when importing third party libraries / components (doing so can bloat the bundle by importing the entire lib) For example, avoid import { Tab } from "x". Prefer import Tab from "x/Tab" when possible.
  • Prefer native HTML inputs over fancy components that simulate native behaviors
  • Use Partytown to load heavy third party libraries via a separate web worker thread

Styling

  • Consider Tailwind to minimize style bundle size
  • Consider CSS modules over CSS-in-JS to avoid a runtime

Framework

  • Consider Gatsby or Astrobuild to compile components into static HTML
  • Consider Next.js, Remix, Redwood to server render

More examples

https://piyushsinha.tech/optimizing-performance-in-react-apps-i
https://piyushsinha.tech/optimizing-performance-in-react-apps-ii

This was referenced May 11, 2022
@STANAPO

Add a comment

Select a reply

Slash commands
Beta
Give feedback
Slash commands
Beta
Give feedback

An unexpected error has occurred

Remember, contributions to this repository should follow our GitHub Community Guidelines.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant