开发工具:Umi + redux-saga + ant-design-mobile + styled-component
使用环境:钉钉浏览器
一、Umi
1, 问题:Umi 版本从1.2.6升级到1.3.1后,使用fetch发送POST请求(Content-type=application/json),一直处于pending状态,一段时间后超时。
定位问题:发现经过代理转发后的请求都会处于pending状态。
解决方案:fetch Content-type 最后要加分号,例如:参考链接
1 | headers: { |
跟进:此问题是由于Umi把mock提到proxy之前引起的,在1.3.5版本修复了,参考链接
2, 问题:升级到1.3.3后,安卓6.0.(努比亚)钉钉打开白屏,使用alert弹出错误内容为使用了保留字。手机自带浏览器打开白屏,IE浏览器白屏并报错`是无效字符
定位问题:Umi-build-dev/lib/utils/guessJSFileFromPath.js 文件中的ES6语法未被解析成 ES5
解决方案:修改nodd_modules下该文件,将ES6语法改为ES5写法。参考链接
3,问题:线上测试版跳转链接时不起作用,后更改modal的namespace起作用了。
原因:因为没进入此namespace页面,按需加载时没有加载到modal。后发现 subscriptions 也只有页面加载后才能调用。
4,问题:Chrome打开页面正常,钉钉浏览器打开页面,显示‘undefined is not a method’。
定位问题:使用Array的find方法,此为ES6语法。
解决方案:引入babel-polyfill
5,问题:服务器启动时浏览器自动打开,配置多系统环境变量。
解决方法:引入cross-env。
6,问题:使用fetch发送请求没有session。
解决方法:加入credentials,值为include或者same-origin。
7,问题:TS类型错误编译可以通过。
解决方案:https://github.com/Umijs/Umi/issues/450
8,问题:配置$id后,同级页面路由会默认走$id
解决方法:在Umi版本1.3.2修复。
二、ant-design-mobile
1, 问题:iOS环境钉钉打开Popover,有时遮罩层会盖住弹框内容。
定位问题:遮罩层的position:fixed引发的层级错乱问题。
解决方案:给overlayStyle加上transform: translated3d(0,0,0)
。
2, 问题:ListView下拉加载卡顿,Popover弹出层的Dom随着ListView加载全部渲染出来。
定位问题:每次获取新数据时都生成一个新的ListView.DataSource。
解决方案:将dataSource更新放在redux里完成。
P.S.本地服务器请求时长不包含卡顿时间,打包后放在服务器上请求时长包含卡顿时间,为什么?
3, 问题:InputItem在blur的时候即使没有改变value也会触发onChange事件。
解决方法:value与props里的value不相等时禁止触发onChange。
4, 问题:Modal滚动穿透
解决方法:把Modal的position改为fixed,详情见链接
5, 问题:Modal.alert中有InputItem,在iOS上刷新页面时InputItem可以聚焦,从其他页面返回后不可以聚焦。
解决方法:使用Modal.prompt无法控制InputItem的显示隐藏,因此使用Modal,如果不加transparent属性,Modal的 animationType是slide-up。点击遮罩层关闭Modal要加上onClose。
6, PullToRefresh的damping不起作用。
定位问题:同这个issue,在antd-mobile2.1.10和 rmc-pull-to-refresh中修复了这个问题。但是项目的antd-mobile已升级到2.1.11,rmc-pull-to-refresh始终是1.0.7
解决方法:由于yarn.lock文件锁住了以来版本,使用 yarn update antd-mobile
三、redux-saga
1, 问题:yield call中使用lodash的debounce报错。
定位问题:因为yield call需要一个返回promise的方法,lodash的debounce不会返回promise。
解决方法:写一个delay的promise。
2, 问题:在地址栏直接输入地址,action的state是POP,在POP时不请求数据,第一次进入无法获取数据。
解决办法:第一次进入页面,state.routing.location是null
跟进:上面解决方法在编译后不起作用,因此将location history存储起来,根据页面地址判断是否从详情返回列表页
四、styled-component
问题:使用styled-component包装后的组件没有ref。
解决方法:styled-component提供了innerRef。
五、钉钉
1, 问题:document.title设置后在钉钉中展示不正常,iOS只显示第一次设置的title,Android会延迟,展示上一个页面的title,使用react-document-title也不行。
解决方法:在钉钉页面中使用钉钉SDK设置title,普通页面使用document.title
1 | if (window.dd) { |
之前iOS使用iframe的onload刷新页面显示正常,然而安卓无效。
1 | setTimeout(() => { |
2, 问题:钉钉sdk里的preview,稍大图片(不到400k)安卓不能预览甚至闪退。
过程:获取到arrayBurrer的图片后用base64转码,用headers里的contnet-type拼接成base64图片,可以用canvas的drawImage压缩图片。此间发现安卓APP上传图片后体积变大好多倍,是因为APP先把图片解成bitmap,400k 一下图片没有压缩处理。修复后有所改善。
解决方法:使用插件react-imageview的singleImgView。该插件不能使用base64。该插件有两个bug,一个是PropTypes定义变量类型报错,注释报错代码就好了。还有一个display:box的warning,会导致每次修改代码服务器挂掉,删除这段代码后暂无发现其他问题。
六、疑难杂症
1, 问题:prettier没起作用 。
原因:忘记安装husky。
2, 问题:接口总是返回参数错误。
原因:忘记设置headers的Content-type为‘application/json’。
3, 问题:新建跟单笔记后返回跟单笔记列表,没有刷出最新数据。
原因:请求接口被浏览器缓存了。
解决方法:在请求中加上时间戳。
4, 问题:合规审核列表的图片返回原图体积过大,大量图片加载会堵塞其他的请求。
解决方法:考虑到后端没有缩略图,只能更改UI做懒加载,点击查看附件时加载图片。
5, 问题:iPhone8(iOS11.0)position:fixed 的元素,当有内容填充的时候,上滑滚动过程中消失。
这是 iOS一个众所周知的bug,但是常见在 iOS9-11(我们的 10,11.3,12 都没有此问题,safari没有问题,只有钉钉有问题)。通常解决方案是translate3d(0,0,0)
开启 GPU 加速。或者在fixed元素前加一个fixed元素。对一些人确实起作用了,但是我们的项目中无效。
除升级系统外,目前暂无解决方案~~
6, 问题:iOS左右滑动翻页时页面闪一下。
解决方法:禁止iOS的翻页手势。翻页要从屏幕最左侧开始滑动,可以返回上一页,无法前进到下一页。
1 | //禁止iOS左右滑动翻页 |
7, 问题:iOS fixed的元素在页面scroll,input聚焦时,fixed失效
解决方法:在focus时把fixed改成absolute,top值为body的scrollTop。但是定位回顶部还是能看到定位的过程。
七、优化过程
上线第一版客户管理后很快迎来了优化。鉴于线上平均访问速度 10 秒以上,首次打开页面白屏时间过长,性能优化是重中之重。
辅助工具:Chrome的Network面板和YSlow
1, 减少请求数
样式改版后由原来使用antd的Icon改为设计师的切图。该页面切图有15个,CSS sprite合并成两张大图,减少了请求数和文件总体积。
2, 减小文件体积
把合成的雪碧图在tinypng.com压缩,体积减少了70%以上,图片质量没有收到影响,而且原图使用的3倍图。压缩后图片都在10K一下,Umi打包后转成base64,并且有memory cache。
3, 优化代码
本项目除使用antd-mobile外还引用了antd的部分组件,主要是Icon,Badge,BackTop。仿antd重写了这几个组件,弃用antd。把公用的CSS、interface提出来。
4, 删除没用的文件和代码
删除没用的依赖如react-document-title,react-copy-to-clipboard,删除文件中没有用到的引用
5, gzip
以Umi.js为例,线上开启了gzip体积是 145K,pre上没有开启,是458K,网络不好时该文件请求时间会超过5s。开启gzip方法参考链接