Blog icon indicating copy to clipboard operation
Blog copied to clipboard

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

Open songxuecc opened this issue 5 years ago • 1 comments

为何写这个文章

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

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。与父组建无关的逻辑就封闭起来。
  1. 对觉得已经不满足后期维护需求,承载负荷过重的代码进行重构。此时代码已经解耦,重构起来会是一件快乐和容易的事情
  2. 对css,动画等进行优化
  3. 删除重复和多余的代码
  4. 分析页面性能,进行具体调整

单测

写单测是和留下组建快照 是代码的一次快照缩影,以后维护中可以验证是否修改最后的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

songxuecc avatar Mar 17 '20 17:03 songxuecc

学习了

zmojm avatar Jun 17 '21 08:06 zmojm