構建利用您的網站的一流應用程序:案例研究
已發表: 2022-03-10Mark 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 內容混合在一起,以創建一個“感覺”原生的應用程序。

案例研究:構建超越機架的應用程序
顯然,重要的是要確定 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 幀的速度運行,用戶會注意到。
我們提出了一種我們認為結合了兩全其美的方法:從網絡加載主要內容,但使用本機導航元素:

在 iOS 上,實現這一點非常簡單。 我們利用了管理視圖堆棧的導航控制器,以及用於控制每個視圖之間導航的導航欄。 在我們的例子中,視圖堆棧實際上只是一堆 Web 視圖——任何時候發生導航,而不是在 Web 視圖本身中導航到它,我們實例化一個新的 Web 視圖,將其推送到我們的UINavigationController
並導航到新的目的地。 使用堆棧的 Web 視圖還意味著無論何時用戶返回,他們都不必等待頁面重新加載,這對他們的體驗來說非常棒。 如果將來我們決定用原生視圖替換一個特性,我們只需將原生視圖推送到堆棧上,而不是該特性的 Web 視圖版本。
在 Android 上,導航控制器的等價物是使用活動堆棧。 我們決定不使用多個活動和片段,因為它們都需要極其複雜的生命週期管理。 我們最終為應用程序管理了自己的 Web 視圖堆棧,並編寫了自定義原生動畫以在每個視圖之間進行轉換。
許多其他應用程序利用本機導航元素來符合操作系統設計模式。 查看 Basecamp 的 Android 應用程序的這張圖片,它利用了原生導航欄:

此外,將亞馬遜的應用程序與其移動網站進行比較:

通過這種方法,我們找到了我們的最佳體驗,即擁有對平台熟悉的體驗,同時仍然利用來自網絡的出色核心購物體驗。
這可能會讓很多人感到驚訝,但 Facebook 應用程序的開發人員也在不斷地尋找最佳位置,在每個功能都有意義時利用本地或網絡。 根據 Facebook 工程師撰寫的一篇文章:“對於應用程序中我們預計會更頻繁地進行更改的區域,我們將繼續使用 HTML5 代碼,因為我們可以在服務器端推送更新,而無需人們下載應用程序的新版本。” 似乎 Facebook 正在採取與這裡提倡的相同方法:根據性能、所需的開發工作量以及將其推出市場所需的速度為每個功能選擇技術。
對於您的應用程序,請根據具體情況考慮是本地構建功能還是利用 Web 內容更有意義。 鑑於構建感覺原生的導航的難度,至少使用原生組件構建它可能是有意義的。
網絡位
今天,幾乎每個人都同意逐步增強網站是一個好主意:使用一個標記庫作為瀏覽器的最低公分母,並根據上下文使用 JavaScript 和 CSS 使用功能和增強對其進行分層——沒有單獨的代碼庫或模板對於不同的設備需要。 就像為移動和桌面網絡創建單獨的模板沒有意義一樣,我們希望在應用程序本身中使用實時網站模板。 該應用程序只是另一個上下文。
我稱這個建築為“應用感知”響應式網站。 通過在考慮應用程序的上下文和性能的情況下構建我們的網站,我們將準備好盡快向各種平台上的所有用戶提供服務。

app
類——逐步增強網站以使其具有應用意識的難題之一。 網站需要能夠在三個地方檢測應用程序上下文:CSS、JavaScript 和服務器。 我們創建了一個app
類來編寫條件 CSS 和一個isRunningInApp
方法來編寫條件 JavaScript,我們將App
附加到用戶代理以實現條件服務器端邏輯。

我們在應用程序中使用漸進增強的一個例子是在我們的產品展示頁面上。 我們通過為應用程序添加一個固定位置的“添加到購物車”按鈕對其進行了優化:

我們也可以在瀏覽器中添加一個固定位置的“添加到包”按鈕,但我們沒有這樣做,因為在 Safari 中,單擊底部附近實際上會打開 Safari 的導航欄。 當用戶嘗試將產品添加到他們的購物車時,此欄意外打開將是一個不可接受的可用性缺陷,儘管在頁面底部有一個持久的“添加到購物車”按鈕有好處:

我們對網站進行特定應用程序調整的另一個區域是購物車。 購物車邏輯通常是任何電子商務網站最棘手的方面之一,因為我們對移動設備上的購物車體驗非常滿意,我們決定在應用程序中重用它,儘管外觀和感覺略有修改:

可共享性
共享鏈接和打開共享鏈接的能力是一個關鍵功能,必須在 Beyond the Rack 中運行良好。 我們希望共享是無縫的。 如果有人從他們的桌面分享了一個鏈接,並且他們的朋友在應用程序中打開了它,則該鏈接需要正確打開; 同樣,如果有人分享應用程序中的產品,它必須在桌面上正確打開; 如果朋友在手機上但沒有安裝應用程序,它應該在瀏覽器中打開。 我們決心讓這成為一次很棒的體驗,因為這通常是應用程序所不擅長的。
使內容在 Web 和應用程序之間共享可能很困難。 要成功地做到這一點,您需要映射您的應用程序鏈接和 Web 鏈接。 這在響應前的日子裡很痛苦,因為重定向等原因,打開桌面 URL 會將您帶到移動 URL 的主頁。 我們今天在應用程序中看到了完全相同的問題——Safari 和 Chrome 中的橫幅要求您在應用程序中打開一個鏈接,只是為了讓該應用程序不顯示您正在尋找的內容,讓您重新搜索它。 幸運的是,在 Beyond the Rack 的應用程序中處理 Web 鏈接是一件輕而易舉的事,因為我們需要做的就是在 Web 視圖中加載該 URL。 我們只需要確保網絡鏈接將用戶帶到應用程序而不是瀏覽器。
在 Android 上,在應用程序中打開 URL 很簡單。 您只需要設置一個意圖過濾器來在用戶嘗試加載指定 URL(在我們的例子中為www.beyondtherack.com
)時加載應用程序。 安裝應用程序後,用戶可以選擇在應用程序或瀏覽器中打開 URL:

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 上不需要權限。 儘管如此,我們認為從客戶服務的角度來看,請求許可是正確的做法。 因此,當用戶第一次登錄應用程序時,我們會詢問他們是否想要通知:
結果
應用發布後,我們想將其性能與瀏覽器體驗進行比較。 直接比較他們的分析是不夠的,因為根據我們的經驗,安裝了該應用程序的任何人都可能是更忠誠的客戶,因此可能會更好地轉換。 為了避免選擇偏差,我們設置了 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 上重複使用它,還是為每個平台定制構建它。
最終,我相信這就是應用程序的構建方式。 但這將需要轉變思維方式。 與其試圖確定網絡是否會戰勝原生或成為過去的遺跡,我們應該擁抱兩者中最好的。 我們應該認識到它們各自的優缺點,並使用對給定功能最有意義的技術。