React+reflu应用 IE8/9/10/11兼容实践
一、挑战
原本的平台业务只在手机移动端上跑,所以日常开发的习惯都是不考虑(也不需要考虑)兼容性的问题。平时会使用很多在低级别浏览器(IE8+)无法运行的API和框架(React、reflux)。在某次合作方接入竞猜平台的需求中,怎么让应用在我们PC端上跑起来,便成了挑战,也是这篇文章的起点~
二、思路/解决
1、分析数据确定方向
首先确定主要攻坚的浏览器版本类型,于是跑到度娘那查了一下全国的浏览器占比数据:
另外要了公司某游戏部门官网的数据:
分析数据得出,chrome、IE8、IE9、IE10、IE11是我们的主要目标。
本次文章主要讲IE8、IE9、IE10、IE11的兼容~ 其他版本太低的IE就不管了:D
2、观察确定记录现状
第二步,在还没做任何兼容措施的情况下,应用出现了以下问题:
postMessage数据传递失效 —— IE9及以下
console对象undefined —— (小部分IE9)及以下
Array对象的isArray方法undefined —— IE8及以下
Object.defineProperty 方法undefined —— IE8及以下
addEventListener兼容性问题 —— (小部分IE9)及以下
操作dom无权限 —— IE9及以下
....
....
咋看一下,问题好像很多。但其实都是一些可以快速兼容的问题。
样式问题这里就不写啦, 重构同学自动背锅。:D
3、对比及确定解决方案
兼容方案方向是用shim/polyfill库来对低级浏览器各个缺失的API、对象做补全。
http://www.cnblogs.com/ziyunfei/archive/2012/09/17/2688829.html
我这里列举了一些github上比较常见、靠谱的方案:
感谢github
1)ieBetter
优点:小而精的polyfill库
缺点:console、Object.defineProperty都没做处理。
2)es5-shim/es5-sham
优点:多而全、可靠的shim库
缺点:console/addEventListener没做容错兼容,Object.defineProperty在某些特殊版本有可能会有问题,但是基本可用。
这作者还有做es6的shim,有兴趣的同学可以了解一下
3)console-polyfill
简单的console兼容库~
4)json3
简单的json兼容库~
5)html5Shiv
html5shiv主要解决HTML5提出的新的元素(section,header,footer)不被IE6-9识别,这些新元素不能作为父节点包裹子元素,并且不能应用CSS样式。html5shiv就是为了解决这个问题存在的。
6)addEventListener-polyfill.js
简单的addEventListener兼容库~
7)ie8
一个IE8的shim库
8)dom4
让IE8获得dom level4的能力
===============================================================
经过各种测试/搭配/组合,得出下面这套比较可靠的方案:有问题欢迎交流...
//es5-shim + es5-sham + console-polyfill + json3 + html5Shiv + addEventListener-polyfill.js//最后一个addEventListener-polyfill.js是直接github Raw下来的,建议自己保存
安利:https://cdnjs.com/ 是个好东西,搜github一些dist文件很方便,而且不用翻墙
三、陷阱/深坑
在引入shim库之后,还踩了挺多莫名其妙的陷阱,下面我一个一个列举出来:
1、IE兼容性文档视图
登过国内网银页面的同学应该都知道,网银的页面一般不兼容高版本的IE,所以IE下有兼容性视图的选项。对于我们来说,有可能会有IE11的用户跑在IE7的模式下面。
- 修复手段
这个陷阱可以通过设置meta来解决:
有兴趣的同学可以通过阅读下方文章,了解这代码的含义:
https://msdn.microsoft.com/zh-cn/library/cc288325
http://www.cnblogs.com/nidilzhang/archive/2010/01/09/1642887.html
2、特定版本React的兼容性问题
处理完陷阱1之后,开始遇到这么一个问题:
直接看error信息,应该是对一个undefined对象引用了length报的错。
为了查明原因,跟进React源码(0.13.0版本的压缩版源码)看 ,发现是IE8下的firstChild.data undefined了。代码片段如下:
e.innerHTML = "" + t;var n = e.firstChild;1 === n.data.length ? e.removeChild(n) : n.deleteData(0, 1);
在IE8下,e.firstChild是一个null对象。所以会导致那样的报错,关于这个bug的文档说明可以参考:
http://www.cnblogs.com/joyeecheung/p/4168521.html
http://www.cnblogs.com/joyeecheung/p/4168521.html
- 修复手段
修复手法是在设置innerHtml的时候,前置一个bom头\uFEFF。
e.innerHTML = "\uFEFF" + t;var n = e.firstChild;1 === n.data.length ? e.removeChild(n) : n.deleteData(0, 1);
但其实,React的0.13.0版本的非压缩版是有做相关处理的(所以一开始我用非压缩版是可以跑起来的)不知道为何min版本却被压没了。超级大坑...
后来在0.13.2版本min下,已经修复了,遂升级了一下我们的React,这个陷阱就跨过去了~
这是折腾了我最久的坑...超级坑...
3、压缩算法导致的问题
搞好了陷阱1、陷阱2之后,遇到了reflux罢工的问题。
定位后发现平台的压缩算法(普通压缩和UglifyJS)。会让模块在IE8有兼容性问题。
大概看了源码,发现可能是混淆压缩之后的对象被覆盖实例化了。这里只是猜测,有兴趣的同学可以自己去研究一下。
单纯用普通压缩,reflux就跑起来了~
4、innerHTML问题
重构同学做了一下关于IE8的css hack:
body{background:# 000 \9;}
重构同学请注意~
- 修复手段
一个\不行就用两个\。
body{background:# 000 \\9;}
四、总结
至此,应用已经能在IE8/9/10/11跑起来了。其中辛酸苦逼无法形容。
定位疑难杂症的时候,应当保持思路清晰,多做排除/置换/简化,来剥离出病因。
卡住了,要多深呼吸冷静下来。再或者去25楼运动一下,说不定有奇效。
如果有什么问题欢迎RTX联系~
后续会补全兼容后的业务数据提升~
五、附件
附件有一个简单的demo,欢迎大家下载使用。
关键字:JavaScript, react.js, reflux, ie8兼容性
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!