构建利用您的网站的一流应用程序:案例研究

已发表: 2022-03-10
快速总结↬ Mark Zuckerberg 曾经说过:“作为一家公司,我们犯下的最大错误是在 HTML5 上押注太多,而不是在原生上……因为它根本不存在。 并不是说 HTML5 不好。 实际上,从长远来看,我对此感到非常兴奋。” 谁不会对跨多个平台工作的单一代码库的前景感到兴奋? 不幸的是,Facebook 认为 HTML5 并没有提供它想要构建的体验,而这正是它真正的意义所在:体验。 我相信 Mark 真正想说的是,他们最大的错误是做出了技术驱动的决策,而不是用户体验驱动的决策。 归根结底,我们应该做出为客户带来价值的决策,而坚持使用特定技术通常不是实现这一目标的最佳方式。

Mark Zuckerberg 曾经说过:“作为一家公司,我们犯下的最大错误是在 HTML5 上投入过多,而不是在原生上……因为它根本不存在。 并不是说 HTML5 不好。 实际上,从长远来看,我对此感到非常兴奋。” 谁不会对跨多个平台工作的单一代码库的前景感到兴奋?

关于 SmashingMag 的进一步阅读

  • 渐进式 Web 应用程序初学者指南
  • 渐进式 Web 应用程序的构建块
  • 在 Foundation For Apps 中创建一个完整的 Web 应用程序

不幸的是,Facebook 认为 HTML5 并没有提供它想要构建的体验,而这正是它真正的意义所在:体验。 我相信 Mark 真正想说的是,他们最大的错误是做出了技术驱动的决策,而不是用户体验驱动的决策。 归根结底,我们应该做出为客户带来价值的决策,而坚持使用特定技术通常不是实现这一目标的最佳方式。

我们的客户 Beyond the Rack 是一家纯在线电子商务零售商,我们的主要目标是构建一个具有出色用户体验的应用程序。 像扎克伯格一样,我们也想走 HTML5 路线——“一次编写,到处运行”的方法对用 HTML5 Web 界面编写的应用程序非常有吸引力。 但在当今世界,应用程序正在成为用户与您的产品交互的主要方式,性能不仅是一件好事 - 它是一种竞争优势。

跳跃后更多! 继续往下看↓

然而,几乎从来没有这样的情况,您的应用程序的所有功能都需要使用完全原生的界面来构建。 例如,虽然可能很难让导航动画在 Web 上感觉是原生的,但一个包含很少甚至没有复杂动画的网页可以很容易地在应用程序中使用,同时仍然感觉原生。 这对用户来说才是真正重要的。 那么需要的是“可能编写一次,可能到处运行——这真的取决于功能……”策略。

简而言之,不要在原生界面和 Web 界面之间进行选择。 两者都用。

在这篇文章中,我将引导您了解我们为 Beyond the Rack 构建应用程序的经验,在该应用程序中,我们将原生和 Web 内容混合在一起,以创建一个“感觉”原生的应用程序。

该应用程序是本机和 Web 界面的混合体
该应用程序是本机界面和 Web 界面的混合体。 (查看大图)

案例研究:构建超越机架的应用程序

显然,重要的是要确定 Beyond the Rack 希望通过其应用程序为自己和客户解决哪些问题。 对于每个功能选择原生还是 Web 将自然而然地产生。

我们意识到,要构建一个出色的应用程序,我们需要在以下三件事上做得很好:

  • 购物界面
    Beyond the Rack 是一家仅在线零售商; 因此,拥有一个用于浏览销售和购买的优秀界面至关重要。 因为我们正在构建一个原生应用程序,所以我们有机会超越 Web 体验所能提供的功能。
  • 可共享性
    因为 Beyond the Rack 的一个主要收入驱动因素是客户与朋友分享各种销售商品,所以我们需要确保 iOS、Android 和浏览器之间的分享尽可能无缝。
  • 可发现性
    Beyond the Rack 向其用户提供限时销售; 因此,能够快速接触到用户非常重要。 推送消息提供了吸引这些忠实客户的最佳方式,它最终是决定构建应用程序的最大驱动力。

让我们深入了解我们如何构建 Beyond the Rack iOS 和 Android 应用程序的一些最重要的功能:应用程序的哪些功能是使用 Web 技术构建的,哪些功能是完全原生的,以及它们如何协同工作。

购物界面

本机位

我们在平板电脑和移动设备上为 Beyond the Rack 建立了一个响应式网站——我们为此感到自豪。 但是,仅仅将网站放入 Web 视图并收工是不够的。 该网站本身并不像本机应用程序。 一个重要的原因是导航。 在浏览器中,您有后退和前进按钮以及 URL 栏。 在 iOS 和 Android 应用程序中,用户对如何导航有非常不同的期望,我们希望满足这些期望,以便我们的应用程序感觉与每个平台保持一致。

我们制作了一个原型,通过 AJAX 动态加载内容并管理 Web 语言中的导航和转换,但我们无法让它像您在本机应用程序中看到的转换那样流畅。 iOS 和 Android 上的导航动画很难使用 Web 技术进行匹配,并且导航中的任何卡顿都会使我们的应用程序感觉不那么原生。 如果您的应用程序没有以每秒 60 帧的速度运行,用户会注意到。

我们提出了一种我们认为结合了两全其美的方法:从网络加载主要内容,但使用本机导航元素:

02-过渡-选择-预览
从一个页面过渡到另一个页面(从左到右),显示应用程序的哪些部分使用本机 UI,哪些部分使用 Web UI。 (查看大图)

在 iOS 上,实现这一点非常简单。 我们利用了管理视图堆栈的导航控制器,以及用于控制每个视图之间导航的导航栏。 在我们的例子中,视图堆栈实际上只是一个 web 视图堆栈——任何时候发生导航,而不是在 web 视图本身中导航到它,我们实例化一个新的 web 视图,将其推送到我们的UINavigationController并导航到新的目的地。 使用堆栈的 Web 视图还意味着无论何时用户返回,他们都不必等待页面重新加载,这对他们的体验来说非常棒。 如果将来我们决定用原生视图替换一个特性,我们只需将原生视图推送到堆栈上,而不是该特性的 Web 视图版本。

在 Android 上,导航控制器的等价物是使用活动堆栈。 我们决定不使用多个活动和片段,因为它们都需要极其复杂的生命周期管理。 我们最终为应用程序管理了自己的 Web 视图堆栈,并编写了自定义原生动画以在每个视图之间进行转换。

许多其他应用程序利用本机导航元素来符合操作系统设计模式。 查看 Basecamp 的 Android 应用程序的这张图片,它利用了原生导航栏:

03-basecamp-opt-预览
Basecamp 将 Web 视图用于有意义的功能。 (图片:信号诉噪声)(查看大图)

此外,将亚马逊的应用程序与其移动网站进行比较:

左侧是亚马逊应用程序中的产品描述页面。右侧是在浏览器中查看的同一产品,显示的内容与应用程序相同,但样式略有不同,并带有原生导航栏。
左侧是亚马逊应用程序中的产品描述页面。 右侧是在浏览器中查看的同一产品,显示的内容与应用程序相同,但样式略有不同,并带有原生导航栏。 (查看大图)

通过这种方法,我们找到了我们的最佳体验,即拥有对平台熟悉的体验,同时仍然利用来自网络的出色核心购物体验。

这可能会让很多人感到惊讶,但 Facebook 应用程序的开发人员也在不断地寻找最佳位置,在每个功能都有意义时利用本地或网络。 根据 Facebook 工程师撰写的一篇文章:“对于应用程序中我们预计会更频繁地进行更改的区域,我们将继续使用 HTML5 代码,因为我们可以在服务器端推送更新,而无需人们下载应用程序的新版本。” 似乎 Facebook 正在采用这里提倡的相同方法:根据性能、所需的开发工作量以及将其推出市场所需的速度为每个功能选择技术。

对于您的应用程序,请根据具体情况考虑是本地构建功能还是利用 Web 内容更有意义。 鉴于构建感觉原生的导航的难度,至少使用原生组件构建它可能是有意义的。

网络位

今天,几乎每个人都同意逐步增强网站是一个好主意:使用一个标记库作为浏览器的最低公分母,并根据上下文使用 JavaScript 和 CSS 使用功能和增强对其进行分层——没有单独的代码库或模板对于不同的设备需要。 就像为移动和桌面网络创建单独的模板没有意义一样,我们希望在应用程序本身中使用实时网站模板。 该应用程序只是另一个上下文。

我称这个建筑为“应用感知”响应式网站。 通过在考虑应用程序的上下文和性能的情况下构建我们的网站,我们将准备好尽快向各种平台上的所有用户提供服务。

应用程序类 - 逐步增强网站以实现应用程序感知的难题之一
一个app类——逐步增强网站以使其具有应用意识的难题之一。

网站需要能够在三个地方检测应用程序上下文:CSS、JavaScript 和服务器。 我们创建了一个app类来编写条件 CSS 和一个isRunningInApp方法来编写条件 JavaScript,我们将App附加到用户代理以实现条件服务器端逻辑。

我们在应用程序中使用渐进增强的一个例子是在我们的产品展示页面上。 我们通过为应用程序添加一个固定位置的“添加到购物车”按钮对其进行了优化:

左,应用程序中的产品展示页面。对了,浏览器中的产品展示页面。
左侧是应用程序中的产品展示页面。 右侧是浏览器中的产品展示页面。 (查看大图)

我们也可以在浏览器中添加一个固定位置的“添加到包”按钮,但我们没有这样做,因为在 Safari 中,单击底部附近实际上会打开 Safari 的导航栏。 当用户尝试将产品添加到他们的购物车时,此栏意外打开将是一个不可接受的可用性缺陷,尽管在页面底部有一个持久的“添加到购物车”按钮有好处:

左侧,以蓝色突出显示的区域将导致 Safari 导航栏打开。对,点击高亮区域的结果。
在左侧,以蓝色突出显示的区域将打开 Safari 的导航栏。 在右边,我们看到了点击高亮区域的结果。 (查看大图)

我们对网站进行特定应用程序调整的另一个区域是购物车。 购物车逻辑通常是任何电子商务网站最棘手的方面之一,因为我们对移动设备上的购物车体验非常满意,我们决定在应用程序中重用它,尽管外观和感觉略有修改:

左,在浏览器中呈现的购物车页面。对,相同的购物车页面,但在应用程序中呈现。
左侧是浏览器中呈现的购物车页面。 右侧,相同的购物车页面,但在应用程序中呈现。 (查看大图)

可共享性

共享链接和打开共享链接的能力是一个关键功能,必须在 Beyond the Rack 中运行良好。 我们希望共享是无缝的。 如果有人从他们的桌面分享了一个链接,并且他们的朋友在应用程序中打开了它,则该链接需要正确打开; 同样,如果有人分享应用程序中的产品,它必须在桌面上正确打开; 如果朋友在手机上但没有安装应用程序,它应该在浏览器中打开。 我们决心让这成为一次很棒的体验,因为这通常是应用程序所不擅长的。

使内容在 Web 和应用程序之间共享可能很困难。 要成功地做到这一点,您需要映射您的应用程序链接和 Web 链接。 这在响应前的日子里很痛苦,因为重定向等原因,打开桌面 URL 会将您带到移动 URL 的主页。 我们今天在应用程序中看到了完全相同的问题——Safari 和 Chrome 中的横幅要求您在应用程序中打开一个链接,只是为了让该应用程序不显示您正在寻找的内容,让您重新搜索它。 幸运的是,在 Beyond the Rack 的应用程序中处理 Web 链接是一件轻而易举的事,因为我们需要做的就是在 Web 视图中加载该 URL。 我们只需要确保网络链接将用户带到应用程序而不是浏览器。

在 Android 上,在应用程序中打开 URL 很简单。 您只需要设置一个意图过滤器来在用户尝试加载指定 URL(在我们的例子中为www.beyondtherack.com )时加载应用程序。 安装应用程序后,用户可以选择在应用程序或浏览器中打开 URL:

Android Intent 用于打开具有特定 URL 的应用程序。在这种情况下,www.beyondtherack.com。
用于打开具有特定 URL 的应用程序的 Android 意图 - 在本例中为www.beyondtherack.com 。 (查看大图)

iOS 在允许 Web URL 直接在应用程序中打开的道路上有些坎坷。 以前,iOS 只允许您为每个应用程序注册一个应用程序架构(例如, beyondtherack:// )。 因为不可能知道安装了哪些应用程序,所以唯一的选择是在 Safari 中打开一个给定的链接,然后从那里尝试在应用程序中打开该链接。 这带来了一个小烦恼:如果没有安装应用程序,用户会收到一条烦人的错误消息,“Safari 无法打开页面,因为地址无效。” 值得庆幸的是,hack 允许您使用 iframe 抑制该错误。 如果你想在 iOS 8 上支持深度链接,这是最好的选择。

值得庆幸的是,iOS 9 引入了通用链接,它允许应用程序在链接通过 Safari 之前拦截网络链接。 ## 可发现性 及时性对于像 Beyond the Rack 这样的公司来说非常重要。 传统上,公司向客户通报销售情况的主要方式是通过电子邮件营销活动。 但是通过应用程序,它能够**直接与客户就销售进行沟通**,这非常强大。 (当然,推送通知正在慢慢进入浏览器,[Chrome 引领潮流](https://gauntface.com/blog/2014/12/15/push-notifications-service-worker)。但对于较旧的 Android 设备对于 iOS,我们已经可以选择是使用原生技术还是使用 Web 技术。)就像共享一样,我们决定直接在应用程序中利用 Web 内容使得设置**推送通知**变得轻而易举。 因为每个产品和销售都可以在网站和应用程序中通过相同的 URL 来识别,所以教育营销人员如何向客户推送通知很简单——他们需要做的就是共享他们习惯共享的相同 URL在电子邮件活动中。 iOS 和 Android 之间的一个有趣区别是推送通知的**权限系统**。 在 iOS 上,通知的权限由操作系统控制,而在 Android 上不需要权限。 尽管如此,我们认为从客户服务的角度来看,请求许可是正确的做法。 因此,当用户第一次登录应用程序时,我们会询问他们是否想要通知:

Beyond the Rack 的 iOS 和 Android 应用程序中的推送通知警报
在 Beyond the Rack 的 iOS 和 Android 应用程序中推送通知警报。 (查看大图)
我们还决定使用 Web 界面构建那些**通知对话框**。 它们不需要任何高级性能,因此使用 Web UI 构建它们并跨平台重用它们是有意义的。 这是让网站应用程序感知的另一个示例:这些对话框是网站的一部分,但有条件地显示在应用程序中。

结果

应用发布后,我们想将其性能与浏览器体验进行比较。 直接比较他们的分析是不够的,因为根据我们的经验,安装了该应用程序的任何人都可能是更忠诚的客户,因此可能会更好地转换。 为了避免选择偏差,我们设置了 A/B 测试; 一半的用户留在应用程序中,一半用户被踢到浏览器,这确保了实验中唯一的参与者是安装了应用程序的用户(更忠诚的用户)。

  • 使用应用程序体验的每位独立访客的​​交易量比使用 Web 的高 76%
  • 该应用的每日唯一身份用户转化的可能性增加了 20%
  • 应用程序用户的浏览时间比网络用户多 63%

快速表现获胜

在 iOS 或 Android 上制作一个加载 Web 内容并感觉原生的应用程序并不是开箱即用的。 以下是我们面临的一些值得分享的性能挑战:

  • 在 iOS 上,Web 视图中的滚动动量与原生滚动视图中的滚动动量不匹配。 这是在用户测试中发现的。 这是解决该问题的一种方法: webview.scrollView.decelerationRate = UIScrollViewDecelerationRateNormal;
  • 调整 Web 视图的大小时要小心。 我们遇到了调整它们的大小会导致整个重绘的问题,这会降低旧设备上的滚动性能。
  • 在 Android 上处理数百种不同的 Web 视图实现可能会很痛苦。 我们遇到的最痛苦的问题是 Android 4.4.2 中的一个已知 Web 视图错误,它在 Chromium 中引发了一个致命的异常,导致应用程序崩溃。 删除该 Android 版本中的transform: translate3d似乎可以解决问题。 或者,您可以使用 Crosswalk 将您自己编译的 Web 运行时与您的应用程序一起发布(我们没有这样做,但我们计划在未来的项目中这样做)。
  • 使用 FastClick,不仅因为它消除了 300 毫秒的点击延迟,还因为它修复了 iOS 8.4.1 中引入的 Web 视图点击错误。 对我们来说,如果点击太慢,则不允许页面更改,从而表现出该错误。
  • 尽你所能让滚动感觉很棒。 您可以消除滚动事件,避免不必要的重绘等等。 如果滚动不是以每秒 60 帧的速度运行,用户会注意到,在应用程序中比在 Web 上更明显。
  • 尽一切可能使页面在 1000 毫秒内加载。

利用您的网站构建应用程序的工具

您有多种选择来构建利用现有网站的应用程序。 我们采用的方法是构建特定于每个平台的应用程序(使用 Xcode 和 Android Studio),必要时利用 Web 视图或本机视图。

在为特定功能加载 Web 视图时,我们建议集成 Cordova Web 视图,而不是直接使用 iOS 和 Android 提供的 Web 视图库。 这将为您的 Web 视图提供许多您必须自己构建的功能,例如从 JavaScript 到本机代码通信的 Web 到本机的桥梁,反之亦然,访问生命周期事件的能力,以及访问丰富的 Cordova 插件。 或者,如果您想避免依赖 Cordova,则可以为各种平台使用其他一些 Web 到本机的桥梁。

有一些框架可以帮助您以这种方式构建应用程序,例如 Supersonic 和 Astro,这是我们正在构建的原生应用程序框架,以便更轻松地管理使用原生和 Web 界面构建应用程序的复杂性。

结论

通过 Beyond the Rack,我们着手构建一个应用程序,在该应用程序中,我们可以在不牺牲体验的情况下轻松地向用户传递价值。 通过遵循将技术置于次要位置的方法,使我们能够使用正确的技术来完成任务,我们相信我们已经实现了这一目标。 随着功能的任何更改或引入,我们总是会问自己,“我们想在这里设计什么样的体验来最好地解决用户的问题? 这种体验是否需要使用高级性能或动画?”

该问题的答案将决定我们是使用 Web 技术构建该功能并在浏览器、Android 和 iOS 上重复使用它,还是为每个平台定制构建它。

最终,我相信这就是应用程序的构建方式。 但这将需要转变思维方式。 与其试图确定网络是否会战胜原生或成为过去的遗迹,我们应该拥抱两者中最好的。 我们应该认识到它们各自的优缺点,并使用对给定功能最有意义的技术。