在JavaScript中检测苹果硅制Mac

23

有没有办法在JavaScript中检测Apple Silicon的Mac?
navigator中的属性似乎不是很有用,例如navigator.platform被设置为MacIntel并且用户代理完全相同。

为什么要这样做:我有两个版本的软件可用,一个用于英特尔处理器,另一个用于Apple Silicon。询问用户“你的Mac是Apple Silicon还是英特尔?”并不是很好的方法。


我不是Mac用户,但你不能提供一个“通用二进制文件”吗?这样,用户的Mac使用什么CPU就无关紧要了。 - gen_Eric
有趣的是,Chrome的下载页面确实会询问用户使用的芯片类型(Apple或Intel)。不过,我认为Chrome的下载可能是通用二进制文件,所以这个并不重要。参见https://support.google.com/chrome/answer/95346 (在“Mac”下面查看,“检查您的Mac配置”)。 - gen_Eric
2
Electron不提供通用二进制文件,这是原因:https://www.electronjs.org/blog/apple-silicon - Antelle
3
Chrome只下载安装程序,然后检查体系结构,再根据其获取实际的东西。对于简单的应用程序来说,这种方法有些过度了。 - Antelle
3
目前,通过WebGL渲染器进行检测只能在Chrome浏览器中使用,因为其他浏览器正在尝试避免平台检测。我在这里制作了一个测试页面:https://browserstrangeness.github.io/detect_mac.gpu.htm,并且还有一个镜像页面:https://browserstrangeness.bitbucket.io/detect_mac.gpu.htm(我相信Google也没有打算将Chrome用于平台检测的方法)。 - Jeff Clayton
3个回答

15

我有一个解决方案,但感觉相当脆弱。

检查操作系统,因为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...
}

如果您看到苹果GPU,则是Safari隐藏了GPU以防止指纹识别。深入了解其能力:

if (w.getSupportedExtensions().indexOf("WEBGL_compressed_texture_s3tc_srgb") == -1) {
  ...probably arm...
}

(我将我的MacBook Pro的性能与新款M1 Air进行了比较,但是Air上缺少了那个。其他所有功能都相同。)

我的做法是给用户选择,但使用此测试来选择默认选项。

如果有人有另一个想法可以帮助缩小范围以确定是否为M1,我很乐意尝试……

更新:正如Romain在评论中指出的那样,苹果在Big Sur中添加了对缺失扩展的支持,因此现在无法使用此方法(在Safari中无法使用;仍可在Chrome和Firefox中使用)。


不错!我同意选择默认选项,这可以是一个很好的测试,至少现在当苹果硅芯片的比例正在缓慢增加时。 - Antelle
4
我有最新版Safari的MacBookAir M1,这个扩展程序不再丢失了。 - Romain

8

由于我只需要在Chrome中进行测试,所以这是一个非常好的解决方案(时间上支持回到v90)。 - Shalanah

4

有一个可以使用的库,它提供有关 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 从 os.arch() 返回 x64 而不是预期结果 arm64 的情况。

编辑:最好将 cpuCore[0].model.includes("Apple M1") 替换为正则表达式或 cpuCore[0].model.includes("Apple"),因为早期版本的 M1 Mac 在型号下返回“Apple 处理器”。


1
os.arch() 不会返回当前计算机体系结构,而是返回应用程序构建的体系结构。 - astoilkov
1
@astoilkov在这个上下文中,“应用程序”是什么意思?我已经引用了官方文档,为什么要使用不同的定义?在大多数情况下,您会期望M1处理器使用M1编译版本的Node.js,这就是为什么我说“arm64”是预期结果的原因。实际上,Node.js被当前操作系统编译是如此之常见,以至于process.arch这个完全相同的函数在文档中给出的示例中暗示它们是相同的。- https://nodejs.org/api/process.html#process_process_arch - InsertKnowledge
1
抱歉,我应该澄清一下。我应该提供上下文而不是盲目地写评论。我所说的用例是Electron。当拥有一个Electron应用程序并且需要知道计算机架构时,但os.arch()会给出应用程序的架构,这取决于用户下载的应用程序版本。 - astoilkov
os.arch 的问题在这里描述:https://github.com/nodejs/node/issues/41900#issuecomment-1113511254 - loretoparisi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接