JavaScript检查PWA或移动Web

99

我想知道是否有基于JavaScript的方法来检测Web体验是否作为PWA(渐进式Web应用程序)运行,还是仅作为带有完整浏览器UI的标准移动网站运行。

已经安装的PWA和没有安装但仍具有服务工作者和/或应用程序缓存注册的PWA之间是否有任何区别?


那个区别有些模糊,因为两者都是基于相同的技术构建的。你想要检测什么? - deceze
3
基本上,无论是作为合法 PWA 安装还是像标准站点一样运行,都可以检查是否安装成功。我对服务工作者和缓存不是很熟悉,但我猜想,即使没有像在手机上那样合法地安装为 PWA,你也可以注册它们两个。也许最好的检查方法是检查浏览器 UI 是否可见,但我不确定是否可以通过 JS 访问该信息。 - PorcupineRending
类似于这个但是针对安卓系统的:https://dev59.com/BWMl5IYBdhLWcg3wJUEC - ikibiki
有没有什么视觉上的区别可以区分PWA和移动Web? - vikramvi
@vikramvi 这取决于PWA的应用程序清单。如果它设置为使用 display-mode: browser 运行,则在视觉上与您的Web浏览器相同。但是,许多PWA使用 standaloneminimal-uifullscreen,这些模式在视觉上有所不同。 - Alex Walker
5个回答

127
如果是为了分析目的,您可以在清单文件中设置起始网址以包括查询字符串参数,例如:
"start_url": "./?mode=standalone"

然后在您的JavaScript中,您可以检查此查询字符串参数。


更新(2020-08-19)

Pete LePage撰写了一篇博客文章,介绍如何使用以下代码设置Google Analytics中的自定义维度,该代码使用window.matchMedia检查显示模式:

let displayMode = 'browser';
  const mqStandAlone = '(display-mode: standalone)';
  if (navigator.standalone || window.matchMedia(mqStandAlone).matches) {
    displayMode = 'standalone';
  }
ga('set', 'dimension1', displayMode);

阅读更多:https://petelepage.com/blog/2020/08/measure-understand-how-installed-pwa-users-differ-from-browser-tab-users/

更新(2017-01-20):

或者您可以使用 JavaScript 进行检查:

if (window.matchMedia('(display-mode: standalone)').matches) {
  console.log("This is running as standalone.");
}

1
更新了我的原始回答,你可以使用以下 JavaScript 代码进行检查:window.matchMedia('(display-mode: standalone)').matches - Kevin Farrugia
谢谢Kevin,这太棒了,看起来完美无缺! - PorcupineRending
@KevinFarrugia 这个检查只在“起始网址”(起始屏幕)上工作吗?还是无论您使用应用程序的哪条路线,它总是存在的? - Alexei S.
@AlexeiS。JavaScript检查将适用于任何页面。 - Kevin Farrugia
如果你想在Android上支持Firefox,查询组件仍然是最佳选择:https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode#browser_compatibility - undefined
显示剩余3条评论

51

2019年10月11日更新: 添加了一个额外的开关来检查应用程序是否通过TWA启动 - document.referrer.includes('android-app://')

这适用于所有应用 - TWA、Chrome和Safari:

const isInStandaloneMode = () =>
      (window.matchMedia('(display-mode: standalone)').matches) || (window.navigator.standalone) || document.referrer.includes('android-app://');

 if (isInStandaloneMode()) {
    console.log("webapp is installed")
}

既然它可能不会改变,将其作为一个变量而不是函数会更有意义。 - stackers
是的,我同意。你知道这是否会带来任何轻微的性能优势吗? - Gary Vernon Grubb
2
我建议保持现状,因为它已经变得非常复杂了。而且,函数是封装事物的最简单方式。在函数调用中节省一个调用栈条目是微不足道的。 - amankkg
1
如果PWA已经被Firefox在Android上添加并启动,那么这对我不起作用。 - mediafreakch
1
似乎在Firefox中存在一个错误,导致matchMedia方法无法正常工作:https://bugzilla.mozilla.org/show_bug.cgi?id=1285858#c29 - mediafreakch
这并不总是有效。如果您的PWA设置为全屏,则display-mode将是全屏而不是独立模式,并且测试可能不正确,因为浏览器可能只是由用户设置为全屏。 - Glenn Maynard

25
if (window.matchMedia('(display-mode: standalone)').matches) {
  console.log("This is running as standalone.");
}

这个答案是正确的,但值得提到的是PWA可以在很多显示模式下运行:

  • 全屏
  • 独立应用
  • 最小化UI
  • 浏览器

如果您在“全屏”模式下运行PWA,它将返回false,因此需要进行额外的检查,例如:

function isPwa() {
    return ["fullscreen", "standalone", "minimal-ui"].some(
        (displayMode) => window.matchMedia('(display-mode: ' + displayMode + ')').matches
    );
}
请注意,即使不是安装的PWA应用程序,“window.matchMedia”检查在“浏览器”显示模式下也会返回“true”。

1
谢谢,那真的帮了我很多... 我把它改写成了这样:function isPwa() { var displayModes = ["fullscreen", "standalone", "minimal-ui"]; return displayModes.some((displayMode) => window.matchMedia('(display-mode: ' + displayMode + ')').matches); } - StPaulis
1
回答不错,但是当我们进行spa构建而不是pwa并在全屏模式下运行时,它也通过了isPwa()的检查。我想检查用户是否在安装模式下使用它。有什么方法可以检查吗? - Hassan Saqib

1
渐进增强是一个概念,而不是一个具体的功能或方法,它涉及多种技术。现在,渐进式 Web 应用程序基于服务工作者,您可以验证浏览器是否支持它。
// Check for browser support of service worker
if ('serviceWorker' in navigator)

项目 lighthouse 可以帮助您通过对多种技术进行评估来检测应用程序是否 渐进增强。快来看看吧。

enter image description here

希望这可以帮助您澄清问题,保留HTML格式,不进行解释。

我想我应该明确一下。这是为了分析目的,所以我想知道是否有一种方法可以使用Javascript告诉某人当前正在查看站点的PWA版本还是常规版本。我在想也许可以检查服务工作者是否已注册,但如果网站尚未“安装”,即使在移动Web上,它也可能已经注册了吧? - PorcupineRending

-4
在我的 PWA 中,使用 Microsoft Visual Studio 2017 创建,以下语句有效:
var isPWA = navigator.userAgent.match(/MSAppHost/i);

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