如何检查浏览器是不是支持 WebAssembly?

Posted

技术标签:

【中文标题】如何检查浏览器是不是支持 WebAssembly?【英文标题】:How can I check if a browser supports WebAssembly?如何检查浏览器是否支持 WebAssembly? 【发布时间】:2018-06-01 11:15:14 【问题描述】:

所有新的主流浏览器都支持 WebAssembly,如何检查当前访问我网站的浏览器是否支持它?

【问题讨论】:

【参考方案1】:

有几种方法可以检测 WebAssembly 的存在。基本的一个是检查WebAssembly是否在全局范围内是"object"类型,但是“全局范围”在不同的javascript环境(主浏览器线程,worker,node.js)中是一件棘手的事情。

这样做在技术上也不够充分,因为您可能拥有 WebAssembly 支持,但由于CSP 而无法实际编译或实例化(而 CSP 不允许的确切内容尚未标准化,工作正在进行中here)。

保守检查可能如下:

const supported = (() => 
    try 
        if (typeof WebAssembly === "object"
            && typeof WebAssembly.instantiate === "function") 
            const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));
            if (module instanceof WebAssembly.Module)
                return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
        
     catch (e) 
    
    return false;
)();

console.log(supported ? "WebAssembly is supported" : "WebAssembly is not supported");

它执行以下操作:

检查WebAssembly在当前范围内是否可以访问。如果它不是全球性的,我们真的不在乎! 查看它是否具有.instantiate 函数,我们实际上并未在此处使用,但您在实际实例化时希望使用该函数,因为它是异步的并且可以在主线程上或关闭处理大型模块。李> 尝试同步编译尽可能小的模块(幻数'\0', 'a', 's', 'm',后跟编码为uint32的版本号1),看看我们是否从中得到WebAssembly.Module。 最后,尝试同步实例化该模块,并检查它是否为WebAssembly.Instance

这有点多,但无论如何都应该工作:

代码在哪里运行(主线程、worker、node.js)。 CSP 如何最终实现标准化。

【讨论】:

一起做了一个快速测试,这个测试用了 1 毫秒,用棒球棒打不过 @GeorgeJempty 我刚刚在 JSBench 上运行它,我在 Safari 上得到了至少 20 倍,在 Chrome 上得到了 6 倍。如果它真的成为网络上的瓶颈,浏览器会对其进行优化。 奇怪,来自this 的 html 代码在 Chromium 74.0.3729.169-2(在 Arch Linux 上)上没有说不支持(红色),但在 Firefox 上却如此;虽然这个答案的代码说两者都不支持。我确实发现 protonmail 在 Chromium 上禁用 webassembly 也很奇怪,我想也许它不再被禁用了:--disable-asm-webassembly --disable-features=AsmJsToWebAssembly --disable-features=WebAssembly,WebAssemblyStreaming 来自here 的Hello world 示例也适用于铬74.0.3729.169-2(但不适用于Firefox)。我猜 WebAssembly 不能再在 chromium 上禁用了,但它可以在 Firefox 69.0a1 (2019-05-26) (64-bit) 上禁用。 好的,可以通过--js-flags=--noexpose_wasm、source禁用chromium webassembly【参考方案2】:

(声誉不足,无法发表评论......) 如果您在旧版浏览器上进行测试,则不支持 () => 语法,因此可以将其全部作为函数来完成:

function wasmSupported() 
    // try/catch, return false; as in JF Bastien's answer

    
if(wasmSupported())  ... 

【讨论】:

但是如果你在旧浏览器上测试 WebAssembly 肯定不支持? @pacukluka 我假设在大多数情况下if 附带else 实际上是为了让最终用户知道网页出了什么问题。

以上是关于如何检查浏览器是不是支持 WebAssembly?的主要内容,如果未能解决你的问题,请参考以下文章

Chromium 宣布:再见 PNaCI,你好 WebAssembly!

如何在浏览器中使用WebAssembly特性

用 WebAssembly 在浏览器中运行 Python

图书WebAssembly实战

Docker 学习总结(78)—— WebAssembly 入门简介

Docker 学习总结(78)—— WebAssembly 入门简介