网络埋伏纪事

原生应用将死

网络埋伏纪事 · 2016-11-21翻译 · 1832阅读 原文链接

从现在起,我将不再创建原生应用,我的所有应用都会是渐进式 Web 应用。渐进式 Web 应用(Progressive web apps,简称 PWA)是被设计为用于移动设备的 Web 应用程序,这种 Web 应用甚至比原生移动应用能更无缝地用于移动设备。

这里的“更无缝地”是什么意思?我指的是如今大部分 Web 流量来自于移动设备,用户平均每个月安装的新应用在 0-3个之间。这意味着人们不会花太多时间在应用商店中寻找新的应用来试用,但是他们会在网上花大量时间,在这里用户可能会发现和使用你的应用。

渐进式 Web 应用程序开始时候跟其它 Web 应用一样,但是当用户回到应用,通过再次使用证明他们对更频繁使用该应用感兴趣时,浏览器会邀请用户将应用安装到用户手机的主屏幕上。PWA 还能像原生应用一样,支持推送通知

这才是它的有趣之处。像所有原生应用一样,渐进式 Web 应用会在移动设备主屏幕上有自己的图标,点击图标时,应用就会不带浏览器边框启动。这意味着没有 URL 地址栏和 Web 导航界面,只有电话平常的状态栏,应用以近全屏的样式出现。

这一天总算来临了。除了新兴的跨平台标准以外,这些技术都不是特别新的。

一些历史

iPhone 出现的早期是没有应用商店的。乔布斯想让开发者用标准 Web 技术创建 iPhone 应用。

有时候有远见的人是对的,只不过是比他们所处的时代提前了十年。两年前,福布斯还称乔布斯推荐为 iPhone 创建 Web 应用是他犯下的“最大错误”,因为原生应用已取得了超级成功。

如今再回顾,好像很明显,他确实是错了某些东西 - 只是高估了当时已有的 Web 标准的能力而已。

十年后,移动 Web 标准现在支持很多在原生应用中才能找到的功能,而乔布斯对移动 Web 应用程序的最初愿景现在正被世界上其他人认真地追求。几乎从使用 meta 标记帮助 iOS 设备找到像合适的图标等事情开始,苹果就已经支持可以添加到主屏幕的 “apple-mobile-web-capable” Web 应用了。

其它厂商也纷纷效仿,每个厂商都创建了各自的一套 meta 标记,声明自己支持移动 Web 应用。但是直到最近,才引入了一套跨平台的规范。现在,跨平台移动 Web 应用才最终成为真事。

实现该标准的应用被称为渐进式 Web 应用,不要把它与渐进式增强或者响应式应用这些相似术语混淆。

什么是渐进式 Web 应用?

渐进式 Web 应用只是被设计为对移动端友好的 Web 应用程序。如果浏览器看到用户想继续使用应用,它会提示用户将其安装到主屏幕上、dock 栏上,等等。不过,要有资格安装到这些地方,应用必须满足如下特定条件:

  • 必须是 HTTPS (参见 let’s encrypt)

  • 带有所需属性的有效 manifest(Web Manifest 校验器

  • 必须有 service worker

  • 即使在离线时,Manifest 中的 start_url 也必须一直加载(用 service worker 加载)

  • 必须自带导航

  • 对于不同屏幕大小和横竖屏必须是响应式的

当然,使用 HTTPS 以及针对离线用户的 Service Worker 对任何现代应用都是好的实践。

很多应用创建者容易忘记的是,如果创建渐进式 Web 应用,必须能在没有浏览器边框以及浏览器导航手势的情况下,也能在应用程序中导航。移动设备假设你已经将自己的导航内置到应用了。

例如,如果有一个 about 页,那么该页面就必须有一个返回到应用程序主界面的链接。否则,为了回到应用的主界面,用户就不得不关闭应用,然后重新打开。

渐进式 Web 应用指南

网上已经有了很多关于创建渐进式 Web 应用程序的信息,不过大部分都是过时的,并且很多只包含创建渐进式 Web 应用所需知识的一小部分。下面我们来解决此问题。

启用 HTTPS

要启用 HTTPS,你将需要:

Manifest 文件

manifest 文件名为 manifest.json,它很简单,由名称(short_name 用于主屏图标,可选的 name 用于更完整的名称)、一个启动 url、一个大的图标列表(如果不同平台需要不同大小的图标,你就可以支持更多平台)组成。对于 Android 和 iOS,将需要:

  • 36x36

  • 48x48

  • 60x60 (iPhone 上的苹果主屏图标)

  • 72x72

  • 76x76 (iPad 上的苹果主屏图标)

  • 96x96

  • 120x120 (iPhone retina 上的苹果主屏图标)

  • 152x152 (iPad retina 上的苹果主屏图标)

  • 180x180 (iOS 8+ 上的苹果主屏图标)

  • 192x192

  • 512x512

我挑出苹果主屏图标,是因为它们的名称很有名: apple-touch-icon-180x180.png

这里的 180x180 可以用任何指定分辨率替换。使用众所周知的名称并非必需,不过如果你忘记了包含这个标记,而你用了众所周知的名称,那么 iOS 依然可以通过在 Web 应用的根目录搜寻,从而找到该图标。

> iOS 图标不支持透明度。

示例 manifest.json:

{
  "name": "My Progressive Web Application",
  "short_name": "Progressive",
  "start_url": "/?home=true",
  "icons": [
    {
      "src": "/icons/icon36.png",
      "sizes": "36x36",
      "type": "image/png"
    },
    {
      "src": "/icons/icon48.png",
      "sizes": "48x48",
      "type": "image/png"
    },
    {
      "src": "/icons/icon60.png",
      "sizes": "60x60",
      "type": "image/png"
    },
    {
      "src": "/icons/icon72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "/icons/icon76.png",
      "sizes": "76x76",
      "type": "image/png"
    },
    {
      "src": "/icons/icon96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "/icons/icon120.png",
      "sizes": "120x120",
      "type": "image/png"
    },
    {
      "src": "/icons/icon152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "/icons/icon180.png",
      "sizes": "180x180",
      "type": "image/png"
    },
    {
      "src": "/icons/icon192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "theme_color": "#000000",
  "background_color": "#FFFFFF",
  "display": "fullscreen",
  "orientation": "portrait"
}

有些功能你应该知道。theme_color 设置在安卓应用之间切换时所用的状态栏和窗口标题栏的颜色。

background_color 设置用在闪屏上的颜色。在安卓上,闪屏将是由 name 属性(长的名字)和 background_color 之上的大图标组成。

Manifest 并非到处都可以用

我第一次创建渐进式 Web 应用程序时,对它按预期在 Chrome for Android 上运行感到兴奋不已。但是当我在 Safari/iOS 中运行时,它貌似不能工作了。原因是,尽管移动版的 Safari 用自定义的标记来支持这些功能已经有十来年左右的时间了,但是它依然还没有支持 Web manifest 规范。

所以,除了对支持了的浏览器使用 manifest 文件外,对于 iOS 你还需要添加一些特殊的 meta 标记。对于 iOS,从如下这个 meta 标记开始,就可以用全屏方式加载应用了:

<meta name="apple-mobile-web-app-capable" content="yes">

还有很多标记要记。不过,还可以采用另一种方法来实现。这里有一个 web manifest polyfill 可以读取你的 manifest.json 文件,并且给对老式移动浏览器、iOS、甚至 Windows Phone 和 Firefox OS 添加上厂商特定的标记。

Service Worker

Service Worker 是一个新的 Web 平台规范,允许在本地缓存资源,从而确保即使在用户断网时应用依然可以用。

其原理是通过劫持网络请求,在用户离线时从本地缓存中提供响应。不过,Service Worker 要做的事情比这个多的多。它是一套相当复杂的低层 API,允许对优化用户体验做很多事情,不管是在线还是离线。

要入门的话,我打算推荐一个很简单的高层抽象。一个很小的叫做 UpUp 的脚本。使用 UpUp 是很简单的。这里有一个来自 UpUp 文档的示例:

`<script src="/upup.min.js">`</script>
<script>
  UpUp.start({
    'content-url': 'schedule.html?user=joe', // 用户离线时显示这个
    'assets': [                 // 定义离线时所需附加资源
      'img/logo.png',           // 比如图像、
      'css/offline.css',        // 定制的样式表、
      'schedule.json?user=joe', // 带有每个用户数据的动态请求、
      'js/angular.min.js',      // JS 库和框架、
      'mov/intro.mp4',          // 视频
      'contacts.pdf'            // 等等
    ]
  });
</script>

content-url 是用户离线时要加载的 URL。我这里就用应用程序的根 URL,而且它工作的不错。

assets 是为了让应用正确运行而需要缓存在本地的文件。记住要确保包含所有图像、图标、CSS,甚至默认的 AJAX 请求响应。正如你所见,任何文件类型可以。

最终,对于缓存的离线资源的控制,你可能想比 UpUp 提供的更多一些。当这一天到来时,这里有一些很不错的教育资源可以帮助你入门:

测试

用 Chrome Devtools 调试物理设备

将设备插到一个 USB 连接线上。在安卓设备上打开 USB 调试功能。查看远程调试指令。你可能需要用 Google 查明关于如何将安卓手机设置为开发者模式,以启用远程调试。

一旦打开开发者模式,就可以看到设置模式中的开发者选项显示出来。打开它,确保 USB 调试是打开的。

访问 chrome://inspect#devices。按下检查(inspect)按钮,会看到应用的全部Dev tools 了。

验证 service worker

访问 chrome://inspect/#service-workers 来验证你的 service worker 是否正确运行。

验证安装到主屏

如果想忽略用户互动度检查,总是得到“安装到主屏(install to homepage)”选项按钮,就在 Chrome flags 中打开“忽略用户互动度检查(Bypass user engagement checks)”:

chrome://flags/

要在桌面上测试的话,还应该打开 “启用添加到任务栏(Enable add to shelf)”。

原生应用还没有灭亡

渐进式 Web 应用现在已经有了原生应用的大部分能力,安装冲突保证也比原生应用更低,你将不再需要担心应用商店把关者,也将不必为在应用商店中的优先权向任何人支付 30% 的应用程序销售税。

但是,可能很长一段时间,原生应用依然具有移动 Web 应用将不具备的一些能力。

尤其是,大多数传感器和硬件集成规格在很多浏览器中是受限制的,或者不支持的。并且,即使是基础功能(比如设备方向 API)也已经经历了重大修改,不同的浏览器中存在有多个版本的规格,要安全使用的话,需要一些繁琐的逻辑或者补丁(polyfills)。

具有讽刺意味的是,尽管苹果开创了很多渐进式 Web 技术,但是 iOS 貌似是采纳渐进式 Web 应用的唯一主要障碍。他们目前不支持 Service Worker,只暗示对添加支持有点兴趣。

值得庆幸的是,有一个 Cordova 插件可以给 iOS 上的混合 app 添加 service worker。

即便如此,我也不指望所有 Web 浏览器厂商以对用户特别友好的方式实现安装提示。用今天的规范,用户也许被也许不被提示安装你的应用,并且如果他们在应用商店中搜索你的应用,除非你也通过传统的应用商店过程出版了一个混合 app,否则他们是找不到的。

短期内,我们也许要坚持使用 Cordava 或者类似的东西来填补 iOS 设备上这一空白,但是对规范的良好支持正迅速在安卓设备上铺开。如果你有台运行 Chrome 的最新安卓电话,那么这就有一个你的应用不需要求助于 Cordova 构建就能工作的好机会。

如果你认为缺乏苹果的支持会拖你后退,请记住安卓现在占有 86% 的全球移动操作系统市场。即使你为了对 86% 的世界利用较低的安装摩擦,而不得不用 Cordova 修补 iOS,创建 PWA 也是值得的。

总结

短期内,你可能依然想开发混合 APP,这样就可以利用一些用 Web 标准依然用不了的设备 API。

在创建第一个渐进式 Web 应用程序后,我对未来充满希望,但是我也意识到它不是完美的。让一切平滑地跨所有设备平台运行确实还需要一段时间。你还需要记住,你还会错失用户在应用商店中熟悉的可发现性功能以及熟知的安装过程。

希望浏览器厂商会追上这个愿景,最终对渐进式 Web 应用会有一个比原生应用更好的安装体验。看起来事情正往这个方向走。

当然,原生应用会留存一段时间,但是如果你为了创建原生应用,正忙于学习 Swift 或者 Java,可能要考虑改为学习 JavaScript。

想试试一些渐进式 Web 应用么?看看 pwa.rocks 吧。

相关文章