专栏名称: 前端加加
前端加加,不给知识设边界。每日精选优质文章,关注我,跟你一起成长~
目录
相关文章推荐
神嘛事儿  ·  哎哟,痛醒,我去,要命 ... ·  5 天前  
节点财经  ·  2025节点增长大会:江南春 周鸿祎 潘飞 ... ·  1 周前  
看金坛  ·  退钱了!退钱了!退钱了! ·  1 周前  
有限次重复博弈  ·  看山姆会员店人山人海的,好像购买力也不弱的样 ... ·  1 周前  
51好读  ›  专栏  ›  前端加加

又骚又准!定位代码问题,离谱操作才神技!推荐你也试试

前端加加  · 公众号  ·  · 2024-05-27 11:21

正文

在你漫长的职业生涯中,你一定会遇到这样一种代码问题:你费尽毕生功能,搞断点、打 log,抓包,google... 各种高端操作轮番上阵,使尽浑身解数,然后,你,依然解决不了它

这种问题,我最近,又双叒叕遇到了... 折腾了半天,底牌尽出,最后,被逼无奈,我直接掏出了压箱底的绝招,一招秒杀,直接搞定。这么好用的方式,必须推荐给大家试试。

  • 一、小程序开发中遇到了一个性能问题
  • 二、艰难而又漫长的问题定位之旅
  • 三、小程序页面切换时页面渲染流程
  • 四、性能优化方案解决方案

本文共 3014 字,阅读预计花费 5 分钟

1

页面切换卡顿

最近发布了我的一款个人小程序前端码易,结果刚一发布,粉丝朋友们就反馈了一大堆问题。其中有一个性能问题把我搞得很麻。

有粉丝在使用过程中发现部分页面的切换动画非常卡顿不流畅。最诡异的是,就那几个页面动画卡顿,其他页面又非常流畅。

页面切换是指从一个页面,跳转到另外一个页面

那我一想,肯定是我的代码有问题啊。所以就去反复查看自己对应几个页面的代码。

可结果却让我很郁闷啊,凭借我十多年的深厚开发功底,学贯前后端的高端技术专家,知命境大成的顶尖修为,翻来覆去看了几遍,居然完全没发现哪有什么问题 ~

无从下手 ~

有点丢人... 自诩资深搬砖,居然一点头绪都没有。不过我依然不动声色。因为我还有底牌未出。这个时机恰恰合适,传给各位道友一个八字真言:

谷歌在手,天下我有!

想好关键词:小程序页面切换卡顿。输入,搞...

定个鬼... 万万没想到,我都换 google 了, 万恶的 CSDN 还缠着我不放  (*  ̄︿ ̄) 。

但是,怀抱着一点希望的我还是再次选择相信。但愿能找到一个雷同的场景,把问题解决掉。点进去,仔细查看文章内容,果然没有惊喜...

微信小程序开发者社区,也不太靠谱,经常提问的一大堆,认真回答的没几个,官方开发团队在这方面也不是很积极。

翻了好几篇文章,终于找了一种说法,可以在全局样式中新增如下属性来解决切换动画卡顿的问题。

page {
  -webkit-overflow-scrolling: touch;
}

病急乱投医试了一下,很可惜没有效果。后来想起来了这条属性是用来解决 iOS 使用 overflow: scroll 滚动不流畅的问题的。

谷歌这条路走不通!

不慌,马上切换战术,祭出性能优化神器 Performance。想必各位道友对此也非常熟悉,对其的掌握肯定也是炉火纯青。点击这个按钮,先来一手记录。

然后我们就去操作页面切换,操作结束后点击 stop 按钮。

然后我们就会得到一张可操作交互的火焰图。如果我们发现哪一块地方被标记为红色了,那么就可能存在问题。

由于操作时间偏长,所以得到的火焰图比较细,看不出什么,我们通过鼠标缩短选中时间,然后下方的火焰图就会变大,变大,变大...

可是,看了半天,试了几次,火焰图表现都挺良好的,也没问题啊... ,硕大一张火焰图,连个线索都不愿意给我提供

这个时候,我就有点慌了呀。底牌出完了... 打断点?也不合适啊,功能没问题,只是一个切换动画卡顿而已

我就想不通了。小程序出来了都快十年了,难道就我遇到了这个问题?别人没遇到?还是大家都这么强,不认为这个问题很难解决?抬抬手就搞定了?压根没有放到网上讨论的必要?

一时之间,我都有点怀疑是不是自己犯了什么低级错误...

然后又像个傻 X 一样去把代码从头到尾看了 1,2,3 遍...

代码看上去,确实没什么问题。

看来,我只能,献祭灵魂,燃烧精血,付出巨大代价,用出我最离谱的一招必杀技:删除定位法

删除代码定位法

1、先删除全部逻辑代码,只留下最简单的页面基础功能,验证页面卡顿是否存在

2、确定删除之后,问题消失。再删除部分代码,逐一排查,执行页面,查看卡顿是否消失

3、如果没有,则继续删除其他部分代码,直到找到问题代码为止

你以为就是简单的删除?不,此法可以暗藏玄机。为了快速定位到问题代码所在,我运用了二分查找法。第二次删除时,我直接删掉上面一半代码,只需要确保留下的代码不报错即可。然后运行验证,我就可以锁定造成卡顿的代码在哪个区间。以同样的方式重复执行,每次都能减少 50% 的搜索区域,直到最后定位到问题代码。

此法离谱确实是离谱,骚也是真骚。它在我的十多年职业生涯中,所向披靡,战功显赫,此法一出,bug 无不闻风丧胆。

果不其然,我最终快速找到了问题所在。

在该页面组件中,我写了这样一段代码

useEffect(() => {
  ad.current = Taro.createRewardedVideoAd({
    adUnitId: ads.ad15
  })
  ...
}, [])

在微信小程序中,createRewardedVideoAd 方法是用来提前创建激励广告实例,以便于读者在点击按钮观看广告时,广告已经创建好了可以直接播放,而不用等待那么久。

万万没想到,该方法居然是一个影响渲染的耗时操作。页面如下

这里一个很具有迷惑性的地方在于,实际上我调用该方法的时机,已经在组件创建完成之后了。所以按照我之前的逻辑,这里不应该会造成卡顿才对。

useEffect(() => {
  // 组件创建完成之后
}, [])

因此,我就有点懵了,为什么组件创建完成之后调用该方法,还是会卡顿呢?

2

小程序页面切换渲染流程

思虑良久,我从结果反推之后,结合小程序的页面切换渲染流程,才想明白问题是如何导致的。

微信小程序页面切换的详细逻辑应该是

1、在当前页面点击按钮
2、创建新页面实例
3、创建完成之后执行入场动画

在这个流程之下我们可以猜想出两种造成页面卡顿的可能。

  • 1、创建页面实例时,执行了太多的逻辑

这种情况的表现为,点击按钮有延迟感,响应不及时。

  • 2、执行入场动画时,执行了耗时任务,跟主线程抢占执行资源

这种情况的表现为,入场动画渲染掉帧,不流畅,卡顿。

3

解决方案

定位到原因,并想明白整个渲染过程之后,解决的方案就非常简单了。我分析了我的几个卡顿的页面,发现上面两种情况都有存在。

先来解决切换动画卡顿的页面。

解决思路就是我们只需要在入场动画执行结束之后,再执行耗时任务即可。微信小程序并没有给开发者提供页面切换动画的具体结束钩子,但是,我们可以使用定时器来推后耗时任务的执行。在定时器中设定一个大概差不多的时间即可。

useEffect(() => {
  setTimeout(() => {
    ad.current = Taro.createRewardedVideoAd({
      adUnitId: ads.ad15
    })
  }, 200)
  ...
}, [])

再保存,重试,发现卡顿的页面流畅了!!!完美解决。

我又分析了另外几个页面,发现还存在另外一种情况的卡顿。

当我点击按钮之后,过了很长时间切换动画才开始执行。

通常情况下,造成这种卡顿的原因是因为页面初始化时执行的逻辑过多,或者渲染的内容多过,导致初始化时间过长,从而造成反应缓慢。解决的办法就是通过懒加载延后处理和渲染非首屏内容

在 React 的项目中,我可以设计一个状态用来阻止大量页面内容在初始化时渲染,先让他渲染主要内容。然后在组件首次渲染完成之后,将该状态设置为 true。当然为了确保内容的渲染不影响动画的执行,我们还可以继续延后 100ms.

一顿操作,调整代码如下

export default function Star({
  const [show, setShow] =  useState(false)
  useEffect(() => {
    setTimeout(() => {
      setShow(true)
    }, 100)
  }, [])

  if (!show) {
    return <div>div>
  }
  
  return (
    <div>这里有四百多个元素div>
  )
}

保存。运行。卡顿的感觉终于全部消失了!!!

给力!