mengtuifrontend / Blog

芦叶满汀洲,寒沙带浅流。二十年重过南楼。柳下系船犹未稳,能几日,又中秋。 黄鹤断矶头,故人今在否?旧江山浑是新愁。欲买桂花同载酒,终不似,少年游。
18 stars 5 forks source link

记录一次有意义的页面和代码优化 #35

Open songxuecc opened 4 years ago

songxuecc commented 4 years ago

为何写这个文章

很少有时间对于写过的代码重构 这次发现重构是真的很有意思的事情 所以就记录下来了

modal的fifo应用

集卡属于互动类型的游戏,此页面有9个弹窗,其中有同时出现的5个弹窗的情况,且如果同时出现必须按照指定顺序弹出。
遇到复杂的交互逻辑,数据结构可以帮助理清思路,抽象逻辑,完成稳定可靠的代码。在这次交互中,弹框要一个个按照顺序弹出,可以虑有序队列。但是弹框的弹出和关闭属于事件。在上一个弹框弹出关闭后,触发下一个弹框弹出。可以考虑事件的发布订阅。

队列图解

队列 是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(end)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队首。

弹窗和队列结合

队列的弹窗展示有三个状态

  1. 同一时间段只有一个弹窗触发
  2. 同一时间段有两个或多个弹窗出发
  3. 一个弹窗在展示过程中,另一个弹窗要触发

整体逻辑分析如下图

用法

import { push } from "./utils"
push(MODAL_TYPE.GIVE_CARD)
push(MODAL_TYPE.ASSIST_CARD)
push(MODAL_TYPE.BUY_CARD)
push(MODAL_TYPE.TASK_CARD)
setTimeOut(()=>{
    push(MODAL_TYPE.RECEIVE_CARD)
},1000)
setTimeOut(()=>{
    push(MODAL_TYPE.ASSIST_CARD)
},4000)

结果

创建enum管理状态

游戏状态多意味着常量多,好的代码最好是不写注释也一目了然。如果可以把注释通过代码表示出来那就太棒了,限制维护者强制书写注释那就更好了。

代码抽离和模块划分

优化后的代码index.js减少了500行左右的代码
我的处理是

  1. 先进行模块划分,把this.renderXXX里的代码放入components里让整体逻辑分离更清晰,把只和子组建相关的逻辑全部移除到子组建中
  2. 首页的ajax多个请求合并,把index.js和store内都会用到的请求都组合再一起,对整体页面init的逻辑整合
  3. 此时再整理首页里面的各种 状态控制锁。将状态控制锁放入constant里。只需要根据不同状态进入不同的组建即可,进行整体的逻辑整合。因为原来的逻辑是 user的状态有4中,活动的状态有4中。这样的排列组合就有16中。需要把这么多排列组合分别在首页逻辑中判断是很复杂的。这里可以考虑根据展示结果判断。同样的展示结果对应哪几种user和activity状态判断组合在一起。后期增加游戏状态时候,只需要再加一个状态和对应的组建即可,也无惧user和活动状态的多变性
  4. 分离出ui组建和容器组建
    • UI组件:只负责页面的渲染
    • 容器组件:只负责业务逻辑和数据的处理,要保证组建功能的完整性,与父组建的交互只需给出回调的callback。与父组建无关的逻辑就封闭起来。
  5. 对觉得已经不满足后期维护需求,承载负荷过重的代码进行重构。此时代码已经解耦,重构起来会是一件快乐和容易的事情
  6. 对css,动画等进行优化
  7. 删除重复和多余的代码
  8. 分析页面性能,进行具体调整

单测

写单测是和留下组建快照 是代码的一次快照缩影,以后维护中可以验证是否修改最后的html结构。用代码描述出最基本的功能,并进行验证。这样保证代码的设计合理性和容易理解的实用性。

加载优化

骨架屏

修改css

使用stylelint检测css一些不和规则的书写
因为css里有一些属性会触发重绘 所以 按照一定的书写顺序可以减少重绘提高css加载速度
而使用简写等可以减少css的打包体积
1. 安装
npm install stylelint --save-dev
npm install stylelint-config-standard --save-dev
npm install stylelint-order --save-dev
2. 在根目录下创建.stylelintrc配置文件
3. 使用
npx stylelint "**/*.css" --fix // fix 是自动修改
4. stylelint的检测提示

下图 是stylelint检测的要修改的点 加入--fix就会自动修改了

对比 虽然很小 但是 量变产生质变 文件多了自然就减少的多了

bundle区分 使用react lazy

const RedBagRain = React.lazy(() =>
  import(
    /* webpackPrefetch: true, webpackChunkName: 'RedBagRain.lazy'*/ "./components/red_bag_rain"
  )
)

<React.Suspense fallback={null}>
              <RedBagRain
                dis_cold_start_selectors={[".mask", ".slidemodal"]}
                visible={!showFinishPage}
              />
            </React.Suspense>

RedBagRain有155 kb ,组建单独打包,分包加载,最后显示分出来 我把modal,actionsheet等 需要点击才能显示出的组建分包加载。这样就达到了首要的包优先加载,其他的包懒加载。如果不需要立即加载的,延迟1000s加载的写法是

const RedBagRain = React.lazy(() => {
  return new Promise(resolve => setTimeout(resolve, 10 * 100)).then(() =>
    import(/*webpackChunkName: 'RedBagRain.lazy'*/ "./components/red_bag_rain")
  )
})

图片压缩

点击进入tiny-图片压缩网站 webpack-bundle-analyzer 分析那些图片太大,如果不是主要图片就进行再次压缩

结果对比

打包结果对比:

优化前

加载结果对比

reference

  1. FIFO和LIFO自动管理modal控制器
  2. 队列在前端弹窗中的应用
  3. Bundle splitting components with Webpack and React
  4. CSS 渲染原理以及优化策略
  5. React Lazy加载的组件丢失其状态(被卸载)
  6. 使用Chrome Performance对页面进行分析优化
  7. CSS代码检查工具stylelint
zmojm commented 3 years ago

学习了