背景
我司新开发了一款App,在windows系统上,App有32位和64两种版本,产品经理希望用户在产品官网下载App时,识别出系统版本,自动下载对应版本的app。也就是需要在网页中识别出cpu架构:64bit还是32bit,并且兼容到ie8。
思路
主流浏览器都提供了navigator.userAgent属性,也就是ua,我们可以从这个属性中得到设备相关信息。在用户下载时直接下载对应版本的App。但是ua是可以伪造的,而且我们也无法保证从ua中得到的信息就是完全正确的,我们永远不知道用户有什么奇奇怪怪的浏览器,所以仍然建议提供一个入口,能够下载全部版本的App。
实现
在github上搜索了一番,看了看star数比较高的几个库
实现思路基本一致,定义枚举值,然后根据ua进行字符串匹配,参照Detect 64-bit or 32-bit Windows from User Agent or Javascript?回答的内容,简单的实现代码如下:
function get_bits_system_architecture() {
var _64bits_signatures = ["x86_64", "x86-64", "Win64", "x64;", "amd64", "AMD64", "WOW64", "x64_64", "ia64", "sparc64", "ppc64", "IRIX64"];
var _bits = 32, _i;
for (_i = 0; _i < _64bits_signatures.length; _i++) {
if (userAgent.indexOf(_64bits_signatures[_i]) != -1) {
_bits = 64;
break;
}
}
return _bits;
}
以上代码存在的问题
在win7 32位 chrome浏览器中运行上述代码,得到的bit数是64。 很神奇是不是,我又在看了一下win7 32位 chrome的ua,Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36,根据上文的代码,得到的结果是win10 x64...这样会导致用户下载错误的包。
经过一番资料查找,我发现新版chrome支持的最低版本是win10,win7只能使用chrome 109及以下的版本,也许是这个原因, 直接通过ua判断得到的结果是错误的。
解决方法
根据微软帮助文档,我们看到了如下代码:
navigator.userAgentData.getHighEntropyValues(["architecture", "bitness"])
.then(ua => {
if (navigator.userAgentData.platform === "Windows") {
if (ua.architecture === 'x86') {
if (ua.bitness === '64') {
console.log("x86_64");
}
else if (ua.bitness === '32') {
console.log("x86");
}
}
else if (ua.architecture === 'arm') {
if (ua.bitness === '64') {
console.log("ARM64");
}
else if (ua.bitness === '32') {
console.log("ARM32");
}
}
}
else {
console.log("Not running on Windows");
}
});
navigator中有一个useragentData属性,可以根据getHighEntropyValues方法得到cpu的架构信息。我们再去看一下chrome下的兼容性
chrome 4 - 89不支持。
终极方案
根据以上的信息我们可以得到一个综合的方案:
注意!!
- 是否为chrome浏览器、浏览器版本、ua识别都可以通过ua-parser-js得到
- Promise代码在低版本ie中运行时,需要引入polyfill
- 本方案得到的结果不一定完全准确