有没有办法在 JavaScript 中检测 Apple Silicon Mac?
navigator
中的属性似乎没有太大帮助,例如,navigator.platform
设置为MacIntel
并且用户代理完全相同。
原因部分:我有两个版本的软件可用,分别用于英特尔和 Apple Silicon。询问用户“您的 Mac 是 Apple Silicon 还是 Intel?”不太好。
我有一个解决方案,但感觉很脆弱。
检查操作系统,因为 Apple Silicon 仅存在于 10_15 或更高版本中:
navigator.userAgent.match(/OS X 10_([789]|1[01234])/)
使用 webgl 检查 GPU:
var w = document.createElement("canvas").getContext("webgl");
var d = w.getExtension('WEBGL_debug_renderer_info');
var g = d && w.getParameter(d.UNMASKED_RENDERER_WEBGL) || "";
if (g.match(/Apple/) && !g.match(/Apple GPU/)) {
...definitely arm...
}
如果您看到 Apple GPU,那么就是 Safari 隐藏了 GPU 以防止指纹识别。深入挖掘能力:
if (w.getSupportedExtensions().indexOf("WEBGL_compressed_texture_s3tc_srgb") == -1) {
...probably arm...
}
(我将 MacBook Pro 的功能与新的 M1 Air 进行了比较,Air 上缺少一个。其他所有功能都相同。)
我采取的方法是给用户一个选择,但使用此测试来选择默认值。
如果有人有其他想法,可能有助于缩小 M1 的范围,我很乐意尝试......
更新:正如 Romain 在评论中指出的那样,Apple 添加了对 Big Sur 中缺少的扩展的支持,因此现在无法使用(在 Safari 中;它仍然可以在 Chrome 和 Firefox 中使用)。
现在可以通过
navigator.userAgentData
实现这一点,尽管并非所有浏览器都支持。
await navigator.userAgentData.getHighEntropyValues(['architecture'])
{
architecture: "arm"
brands: [{…}, {…}, {…}],
mobile: false,
platform: "macOS"
}
https://developer.mozilla.org/en-US/docs/Web/API/NavigatorUAData/getHighEntropyValues
您可以使用一个库,为您提供有关 Node.js 中操作系统的信息 - os (
const os = require('os')
)。它有一个返回 cpu 核心的方法 - os.cpus()
,您只需获取第一个元素并检查它是否是您想要的确切型号,或者它是否在其模型中仅包含“Apple M1”作为字符串 - let isM1 = cpuCore[0].model.includes("Apple M1")
。
您还可以检查
os.arch()
方法:
返回 Node.js 所在的操作系统 CPU 架构 二进制文件已编译。
不过,我建议在使用 arch 方法时高度谨慎,因为我曾经发生过几次,其中 M1 Mac 从
x64
返回 os.arch()
,而不是预期的结果arm64
。
编辑:可能最好用正则表达式或
cpuCore[0].model.includes("Apple M1")
替换 cpuCore[0].model.includes("Apple")
,因为最早版本的 M1 mac 在型号下返回“Apple 处理器”。
我为此使用 UAParser.js V2,它是免费且开源的。 https://github.com/faisalman/ua-parser-js
在 V2 中,他们添加了一个
withClientHints
链式函数,它返回一个 Promise。在底层,它使用了 user3717031 提到的 getHighEntropyValues
方法。可以这样使用:
UAParser().withClientHints().then(function(result) {
var CPU = result.cpu.architecture; // returns "arm64" on macOS ARM
});