# React 项目中有哪些细节可以优化,实际开发中都做过哪些性能优化

# 往期回顾

# 1. 自定义轮询时间为 a, a+b, a+2b....a+nb

function aa(a, b) {
  this.a = a;
  this.b = b;
  this.i = 0;
  this.timer = null;
  this.start = () => {
    const b = this.b * this.i;
    this.i++;
    this.timer = setTimeout(() => {
      this.start();
      console.log(this.a + b);
    }, this.a + b);
  };
  this.clear = () => {
    if (this.timer) {
      clearTimeout(this.timer);
    }
  };
}

# 归并排序

function myFlat(arr){
  return arr.reduce((acc, cur)=>{
    return Array.isArray(cur)? [...acc, ...myFlat(cur)]:[...acc, ...cur];
  },[])
}
funtion mySort(arr, key){
  return arr.sort((a,b)=>a[key]-b[key]);
}

# 查找不重复最长字符串

const strL = "ssssasdasqweqweqw";
let arr = [];
let len = 0;
let strLen = "";
const strLCopy = strL.split("");
for (let i = 0; i < strLCopy.length; i++) {
  if (arr.indexOf(strLCopy[i]) > -1) {
    arr = [];
  }
  arr.push(strLCopy[i]);
  if (arr.length > len) {
    len = arr.length;
    strLen = strLen + strLCopy[i];
  }
}

# 谷歌版本

# 1. 金丝雀 一天多次

# 2. 开发者 一周一次

# 3. 测试 一月一次

# 4. 稳定 一月一次

# React 项目中有哪些细节可以优化,实际开发中都做过哪些性能优化

# 1)实际项目中开发过程有哪些优化点

  • 保证数据的不可变性
  • 使用唯一的键值迭代
  • 使用 webWork 做密集型的任务处理
  • 不在 render 中处理数据
  • 不必要的标签,使用 React.Fragments

# 2)对于正常的项目优化,一般涉及到几个方面,开发过程中,上线之后的首屏,运行过程的状态

  • 首屏优化一般涉及到几个指标=》FP, FCP, FMP;要有一个良好的体验是尽可能的把 FCP 提前,需要做一些工程化的处理,去优化资源的加载。
  • 方式和分包策略:资源减少是最有效的加快 首屏打开的方式
  • 对于 CSR 的应用,FCP 的过程一般是首先加载 js 与 css 资源,js 在本地执行完成,然后加载数据回来,做内容初始化渲染,这中间就有几次的网络反复请求的过程,所以 CSR 可以考虑使用骨架屏及预渲染(部分结构预渲染),suspence 与 lazy 做懒加载动态组件的方式
  • 另一种方式是 SSR,SSR 对于首屏的优化有一定的优势,但瓶颈一般在 Node 服务端的处理,建议使用 stream 流的方式来处理,对于体验与 node 端的内存管理等都有优势
  • 不管对于 CSR 还是 SSR,都建议配合使用 Service worker 来控制资源的调配及骨架屏秒开的体验
  • react 项目上线之后,首先需要保障的是可用性,可以使用 React.Profiler 分析 组件的渲染次数及耗时的一些任务,但 profile 记录的是 commit 阶段的数据,所以对于 react 的调和阶段就需要结合 performanceAPI 一起分析
  • 可以用 React 的 PureComponent 以及 React.memo 等做浅比较处理,避免父级 props 改变后,所有的 props 不相关的子组件在没有添加条件控制的情况下渲染,也可以用 ShouldComponentUpdate 做深比较处理
  • 所有运行状态的优化,都是减少 render 次数,React.useMemo 与 React.useCallback 也是可以做很多优化的地方
  • 谨慎处理 redux 及 context 的数据
  • 最后为了保证整个应用的可用性,为组件创建错误边界,可以使用 componentDidCatch 来处理