有消息称 Chrome 冻结了他们的 User-Agent 字符串(所有其他主要浏览器也都加入了)。 这意味着他们仍然拥有 User-Agent (UA) 字符串(在标头中显示,并且在 JavaScript 中可用,如 navigator.userAgent
)。 通过冻结它,它在检测浏览器/平台/版本方面将随着时间的推移而变得不那么有用,尽管这样做的原因是更多地出于隐私考虑,并阻止指纹识别,而不是开发人员的担忧。
在前端世界,普遍的建议是:你不应该进行 UA 探测。 主要问题是太多网站弄错了,他们使用该信息进行的更改最终弊大于利。 避免它的普遍建议是:你应该根据你正在尝试做的事情的实际情况进行测试。
你是否想测试浏览器是否支持特定功能? 那么测试该功能,而不是抽象的特定浏览器概念,该浏览器应该支持该功能。
在 JavaScript 中,有时功能非常容易测试,因为你可以测试其 API 的存在
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
console.warn("Geolocation not supported");
}
在 CSS 中,我们有一个原生机制,通过 @supports
@supports (display: grid) {
.main {
display: grid;
}
}
它通过一个 API 在 JavaScript 中公开,该 API 返回布尔值答案
CSS.supports("display: flex");
并非 Web 平台上的所有内容都这么容易测试,但通常可以不进行 UA 探测就能做到。 如果处于困境,始终值得检查Modernizr 是否有针对它的测试,这算是功能测试的黄金标准,因为很有可能它已经过实战测试,并且以你可能无法预见的方式处理了边缘情况。 如果你实际上使用该库,它会为你提供清晰的逻辑断点
if (Modernizr.requestanimationframe) {
// supported
} else {
// not-supported
}
如果你只是确实需要知道浏览器类型、平台和版本? 好吧,显然仍然可以通过一种名为User-Agent 客户端提示 (UA-CH) 的新方法获取这些信息。
想知道平台吗? 你可以在请求中设置一个名为 Sec-CH-Platform
的标头,理论上,你将在响应中获得该信息。 你必须主动索取它,这显然足以防止出现有问题的隐私指纹识别问题。 似乎有类似 Sec-CH-Mobile
的标头,用于移动设备,这有点奇怪。 谁来决定什么是“移动”设备? 我们应该用它做出哪些决定?
在服务器级别了解有关浏览器、平台和版本的的信息通常也是可取的(在不同情况下发送不同的代码)——与客户端一样多,但没有测试的优势。 可以推测,冻结的 UA 字符串将足够长,以便服务器端情况可以移植到使用 UA-CH。
在职业生涯中,我一直致力于移动网页空间,并亲眼见证了它在 15 年多的时间里不断发展,我知道许多大型和小型网站都依赖于基于
User-Agent
标头的设备检测。 从 Google 的角度来看,切换到替代的 UA-CH 可能看起来很容易,但问题是推动这项变革的团队不了解其影响基于设备检测的功能至关重要,广泛存在,不仅仅在前端代码中。 巨大的软件系统,包括后端代码,都依赖于设备检测,以及整个基础设施堆栈。
在我的主要代码库中,我们进行了一些服务器端 UA 检测。 我们使用名为 Browser 的 Rails gem,它以一个漂亮的 API 公开 UA 衍生的信息。 我可以写
if browser.safari?
end
我们还公开了该 gem 中的客户端信息,以便它也可以在客户端使用。 只有少数前端和后端的使用实例,没有一个看起来很难以其他方式处理。
过去,将前端信息以在首頁加载时有用的方式中继回服务器有点棘手(因为 UA 不了解视窗大小等信息)。 我记得我做过一些相当花哨的操作,我加载一个骨架页面,它执行一小段 JavaScript 代码,这些代码做的事情就像测量视窗宽度和屏幕大小,然后设置一个 cookie 并强制刷新页面。 如果 cookie 存在,服务器将拥有所需的信息,并且不会在这些请求中加载骨架页面。
很棘手的东西,但然后服务器将拥有服务器端的视窗宽度信息,这对某些事情很有用,比如发送小屏幕资产(例如,不同的 HTML),否则这是不可能的。
我提到这一点是因为 UA-CH 东西不要与普通的客户端提示混淆。 我们应该能够配置我们的服务器发送一个 Accept-CH
标头,然后让我们的客户端代码将要发送回的东西列入白名单,例如
<meta http-equiv="Accept-CH" content="DPR, Viewport-Width">
这意味着服务器可以在后续页面加载时从客户端获取有关这些事项的信息。 这是一个不错的 API,但 Firefox 和 Safari 不支持它。 我想知道,如果这两个浏览器都对 UA-CH 表现出兴趣,是因为这个冻结的 UA 字符串问题,它是否会得到提升。
当然,依赖于浏览器的功能是最好的方法。 如果它是功能问题。
请记住 IE6 中关于浮动情况下双倍边距的旧错误。 这是一个错误。 你不能要求浮动或边距的所谓支持来修复此问题。 你必须知道面前的是否是 IE6(或者使用其他技术,当然可以,但这并非重点)。
使用
transform: translateX()
时,溢出的元素与 IE11 中的水平滚动条的情况相同。其他情况,
<input type="number" />
的渲染方式因浏览器而异,这不仅仅是功能问题。 你无法测试它。你也会对同一情况有不同的解释,所以支持是官方存在的,但反应不同。
当一切都完美,甚至标准得到尊重时,公平地说,但这只是“决定”不会出现错误。 或者至少无法解决某些错误。 对我来说有点武断。
确实! 我很高兴 Edge 选择了 Chromium。
我希望 Safari 也能这样做,弹性盒子和网格布局太糟糕了。
只有在正确实施标准的情况下,多样性才会有利。
考虑到 Google 有通过 UA 探测有意提供更差体验的历史,这很有趣。
事实上,他们今天仍在这样做,使用 Stadia。
那么,不使用黑客技术,使用 CSS 目标特定浏览器的最佳方法是什么? 在必要时,我一直使用一个 JS 库,该库将浏览器的 User-Agent 添加到 HTML 标签中,作为用于使用的类。
这很好,因为许多人在可以使用功能检测的情况下使用 User-Agent。 这是不好的,因为可能存在一些无法检测到的错误,并且通过冻结 UA 字符串,人们将需要
依赖于像指纹识别功能支持这样的黑客行为来检查浏览器是否存在错误。
假设所有浏览器都存在错误,并始终解决它。
忽略错误并导致故障。
据我所知,上次我看到这样的错误是在我使用 Service Worker 进行实验时,与 Chrome 不同,某些 Safari 版本忽略了文件下载的 worker,这无法使用通常的功能检测方法来检测。 我不知道这个问题是否仍然存在,但在当时,这个“错误”非常糟糕,因为解决方法非常消耗内存。 导致故障将很糟糕,因为没有解决方法,Safari 将下载错误的文件(据我所知,它是一个包含错误消息的 HTML)。
请求浏览器版本有正当理由。 通过自动化测试 Web 软件。 某些东西在一个版本中可以正常工作,但在另一个版本中会产生错误。 看起来这会导致很多“当我运行 Chrome 时,它在我的手机上运行良好”,当报告错误并发送到农场中使用自动化进行测试时。