当前位置: 首页 > 科技观察

详细判断浏览器的运行环境,值得阅读

时间:2023-03-19 18:02:56 科技观察

看到前言中的标题,就可以想起来这个需求可以用在很多项目中。我们部署在web服务器上的前端应用,PC浏览器和手机浏览器都可以访问。再加上智能设备的推广,我们甚至可以在车载系统、可穿戴设备和电视平台上接入。设备的多样化使得用户无处不在,有时我们需要根据不同的浏览器运行环境做出相应的处理。浏览器是JavaScript的载体,我们可以从浏览器获取相关信息,进一步处理我们的业务逻辑。但浏览器品牌众多,部分浏览器使用标准不同,难以统一判断。下面我就大致罗列一下常用的浏览器品牌以及在什么情况下使用浏览器运行环境来判断。可以在此处找到与浏览器相关的统计信息。前五名国际浏览器品牌:按全球使用量降序排列GoogleChrome:Windows、MacOS、Linux、Android、iOSAppleSafari:MacOS、iOSMozillaFirefox:Windows、MacOS、Linux、Android、iOSASAOpera:Windows、MacOS、Linux,Android,iOSMicrosoftInternetExplorerorMicrosoftEdge:Windows国内常见浏览器品牌:按国内使用量降序排列,一般基于开源项目Chromium开发微信浏览器QQ浏览器UC浏览器2345浏览器搜狗浏览器猎豹浏览器傲游浏览器百度浏览器:百度于2019年4月30日宣布停止服务其他浏览器:还有很多很多,数不胜数,这里就不一一列举了。Chromium进行了二次开发,额外加了一层壳。不得不说,自己开发的浏览器是全球第五大浏览器。被眼尖的网友发现了。详情请点击一、二、三。...使用场景判断用户浏览器是桌面端还是移动端,显示对应的主题样式,判断用户浏览器是安卓还是iOS,跳转到对应的App下载链接,判断用户浏览器是微信还是H5,调用微信分享或分享当前浏览器,获取用户浏览器的内核和载体,用于统计用户设备平台的分布范围,获取用户浏览器的载体版本,提示更新信息。其实使用场景还有很多,就不一一举例了。针对这样的使用场景,其实还有一个更专业的名字叫浏览器指纹识别。上面我们提到的需求只是浏览器指纹方案的一小部分,我们需要用到的浏览器指纹就是UserAgent。这个用户代理在哪里?中文翻译为UserAgent。引用百度的定义,是一个特殊的字符串头,可以让服务器识别客户端使用的操作系统及版本、CPU类型、浏览器载体及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。而这些信息足以让我们判断浏览器的运行环境。准备网上很多方案只是针对系统是桌面端还是移动端,安卓还是iOS,部分浏览器运营商等的判断和获取,并没有完美或者终极的方案。所以我用了很多测试平台,整理出一个比较全面的方案。本方案包括浏览器系统及版本、浏览器平台、浏览器内核及版本、浏览器载体及版本、浏览器外壳及版本。而这个方案也是基于navigator.userAgent获取浏览器的相关信息(如下),然后通过系统、平台、内核、载体、外壳等特有的字段进行分类统一,梳理出一个完整的浏览器运行环境。constua=navigator.userAgent.toLowerCase();//输出“Mozilla/5.0(iPhone;CPUiPhoneOS11_0likeMacOSX)AppleWebKit/604.1.38(KHTML,likeGecko)Version/11.0Mobile/15A372Safari/604.1”浏览器信息:权重降序排列命令浏览器系统:运行的操作系统,包括Windows、MacOS、Linux、Android、iOS浏览器平台:运行的设备平台,包括Desktop和Mobile浏览器内核:浏览器渲染引擎,包括Webkit、Gecko、Presto、Trident浏览器载体:五种主要浏览器品牌,包括Chrome、Safari、Firefox、Opera、Iexplore/Edge浏览器外壳:基于五大浏览器品牌的核心开发,再一层自研技术外壳,比如国内很多浏览器品牌获取UserAgent是否包含字段:判断是否包含系统、平台、内核、运营商、外壳的特有字段consttestUa=regexp=>regexp.test(ua);获取UserAgent对应字段的版本consttestVs=regexp=>(ua.match(regexp)+"").replace(/[^0-9|_.]/ig,"").replace(/_/搞笑,“。”);以上准备工作完成后,根据权重(系统+系统版本>平台>内核+载体+内核版本+载体版本>外壳+外壳版本)system,platform,kernel,carrier,shell统一浏览器运行环境分类的唯一字段。系统+系统版本//systemletsystem="unknown";if(testUa(/windows|win32|win64|wow32|wow64/ig)){system="windows";//window系统}elseif(testUa(/macintosh|macintel/ig)){system="macos";//macos系统}elseif(testUa(/x11/ig)){system="linux";//linux系统}elseif(testUa(/android|adr/ig)){system="android";//android系统}elseif(testUa(/ios|iphone|ipad|ipod|iwatch/ig)){system="ios";//ios系统}//系统版本letsystemVs="未知";if(system==="windows"){if(testUa(/windowsnt5.0|windows2000/ig)){systemVs="2000";}elseif(testUa(/windowsnt5.1|windowsxp/ig)){systemVs="xp";}elseif(testUa(/windowsnt5.2|windows2003/ig)){systemVs="2003";}elseif(testUa(/windowsnt6.0|windowsvista/ig)){systemVs="vista";}elseif(testUa(/windowsnt6.1|windows7/ig)){systemVs="7";}elseif(testUa(/windowsnt6.2|windows8/ig)){systemVs="8";}elseif(testUa(/windowsnt6.3|windows8.1/ig)){systemVs="8.1";}elseif(testUa(/windowsnt10.0|windows10/ig)){systemVs="10";}}elseif(system==="macos"){systemVs=testVs(/osx[\d._]+/ig);}elseif(system==="android"){systemVs=testVs(/android[\d._]+/ig);}elseif(system==="ios"){systemVs=testVs(/os[\d._]+/ig);}平台letplatform="unknow";if(system==="windows"||system==="macos"||system==="linux"){platform="desktop";//desktop}elseif(system==="android"||system==="ios"||testUa(/mobile/ig)){platform="mobile";//mobile}内核+运营商letengine="unknow";letsupporter="unknow";if(testUa(/applewebkit/ig)&&testUa(/safari/ig)){engine="webkit";//webkit内核if(testUa(/edge/ig)){supporter="edge";//edge浏览器}elseif(testUa(/opr/ig)){supporter="opera";//opera浏览器}elseif(testUa(/chrome/ig)){supporter="chrome";//chrome浏览器}else{supporter="safari";//safari浏览器}}elseif(testUa(/gecko/ig)&&testUa(/firefox/ig)){engine="gecko";//gecko内核支持者="firefox";//firefox浏览器}elseif(testUa(/presto/ig)){engine="presto";//prestokernelsupporter="opera";//operabrowser}elseif(testUa(/trident|compatible|msie/ig)){engine="trident";//tridentkernelsupporter="iexplore";//iexplore浏览器}内核版本+运营商版本//内核版本letengineVs="unknow";if(engine==="webkit"){engineVs=testVs(/applewebkit\/[\d.]+/ig);}elseif(engine==="gecko"){engineVs=testVs(/gecko\/[\d.]+/ig);}elseif(engine==="presto"){engineVs=testVs(/presto\/[\d.]+/ig);}elseif(engine==="trident"){engineVs=testVs(/trident\/[\d.]+/ig);}//运营商版本letsupporterVs="unknown";if(supporter==="chrome"){supporterVs=testVs(/chrome\/[\d.]+/ig);}elseif(supporter==="safari"){supporterVs=testVs(/version\/[\d.]+/ig);}elseif(supporter==="firefox"){supporterVs=testVs(/firefox\/[\d.]+/ig);}elseif(supporter==="opera"){supporterVs=testVs(/opr\/[\d.]+/ig);}elseif(supporter==="iexplore"){supporterVs=testVs(/(msie[\d.]+)|(rv:[\d.]+)/ig);}elseif(supporter==="edge"){supporterVs=testVs(/edge\/[\d.]+/ig);}shell+shellversionletshell="none";letshellVs="unknow";if(testUa(/micromessenger/ig)){shell="wechat";//微信浏览器shellVs=testVs(/micromessenger\/[\d.]+/ig);}elseif(testUa(/qqbrowser/ig)){shell="qq";//QQ浏览器shellVs=testVs(/qqbrowser\/[\d.]+/ig);}elseif(testUa(/ubrowser/ig)){shell="uc";//UC浏览器shellVs=testVs(/ubrowser\/[\d.]+/ig);}elseif(testUa(/2345explorer/ig)){shell="2345";//2345浏览器shellVs=testVs(/2345explorer\/[\d.]+/ig);}elseif(testUa(/metasr/ig)){shell="sougou";//搜狗浏览器}elseif(testUa(/lbbrowser/ig)){shell="liebao";//猎豹浏览器}elseif(testUa(/maxthon/ig)){shell="maxthon";//漫游浏览器shellVs=testVs(/maxthon\/[\d.]+/ig);}elseif(testUa(/bidubrowser/ig)){shell="baidu";//百度浏览器shellVs=testVs(/bidubrowser[\d.]+/ig);}最终拟合根据以上条件得到的变量如下,我们可以把它们合并成一个对象输出,这样就可以输出一个清晰的浏览器运行环境,以后想干什么就干什么,多方便啊。本文着重探讨方案的可行性,并没有过多考虑代码优化,所以条件判断用的比较多。如果有什么优化代码,减少条件判断的方法,可以在下方评论提出建议。system:systemsystemVs:系统版本platform:platformengine:kernelengineVs:内核版本supporter:carriersupporterVs:carrierversionshell:shellshellVs:shellversionfunctionBrowserType(){constua=navigator.userAgent.toLowerCase();consttestUa=regexp=>regexp.test(ua);consttestVs=regexp=>(ua.match(regexp)+"").replace(/[^0-9|_.]/ig,"").replace(/_/ig,".");//接上面if...else条件判断//...//获取system,systemVs,platform,engine,engineVs,supporter,supporterVs,shell,shellVsreturnObject.assign({engine,//webkitgeckoprestotridentengineVs,platform,//desktopmobilesupporter,//chromesafarifirefoxoperaiexploreedgesupporterVs,system,//windowsmacoslinuxandroidiossystemVs},shell==="none"?{}:{shell,//wechatqquc2345sougouliebaomaxthonbaidushellVs}}serrow;),该出来的都出来了,哈哈!源码详情请点这里,喜欢的话可以点个赞支持一下,谢谢。结论和最后的结论几乎一样。如果我想到判断浏览器运行环境的终极解决方案中有什么遗漏的项目,我会继续完成这篇文章。同时,也希望各位顽固的朋友能够对文章中的要点进行补充或补充。提出自己的看法。欢迎在下方评论或补充,喜欢的可以点赞或收藏,保证开发中能用得上。