我們很高興為大家介紹全新Twitter Lite,一款已經(jīng)于mobile.twitter.com上正式發(fā)布的漸進(jìn)式Web應(yīng)用(PWA)。Twitter Lite擁有快速與交互式特性、使用更少數(shù)據(jù)、占用更低存儲空間且可在現(xiàn)代瀏覽器當(dāng)中支持推送通知與離線使用模式。目前,Web已經(jīng)成為輕量級應(yīng)用程序的運(yùn)行平臺,可輕松實(shí)現(xiàn)按需訪問、順暢安裝以及逐步更新等優(yōu)勢。在過去一年中,我們采用了多種新型開放式Web API,并顯著提升了性能水平與用戶體驗(yàn)。
架構(gòu)概述
Twitter Lite是一套移動端的JavaScript應(yīng)用程序,同時亦是一款小型的簡單Node.js服務(wù)器。該服務(wù)器負(fù)責(zé)處理用戶身份驗(yàn)證、構(gòu)建應(yīng)用程序初始狀態(tài)并將結(jié)果呈現(xiàn)至初始HTML應(yīng)用程序shell。在被加載至瀏覽器當(dāng)中后,應(yīng)用程序?qū)⒅苯油ㄟ^Twitter API請求相關(guān)數(shù)據(jù)。這種基本架構(gòu)的簡單特性使得我們能夠提供卓越的服務(wù)可靠性與運(yùn)行效率——事實(shí)上,Twitter Lite的運(yùn)行成本相較于使用服務(wù)器渲染型桌面網(wǎng)站要低出一個量級。
這款客戶端側(cè)JavaScript應(yīng)用程序已經(jīng)配合多款開源庫進(jìn)行了開發(fā)、構(gòu)建與測試,具體包括React、Redux、Normalizr、Globalize、Babel、Webpack、Jest、WebdriverIO以及Yarn。憑借著現(xiàn)有開源軟件,我們得以將更多時間與精力投入到提升用戶體驗(yàn)、增加迭代速度以及推文數(shù)據(jù)與時間軸的處理與操作等相關(guān)解決方案當(dāng)中。
我們編寫的現(xiàn)代JavaScript代碼(ES2015及更高)由Babel編譯完成,并同Webpack加以綁定。API響應(yīng)數(shù)據(jù)首先由Normalizr進(jìn)行處理——其允許我們進(jìn)行重復(fù)條目刪除并將數(shù)據(jù)轉(zhuǎn)化為更為高效的形式——而后被發(fā)送至多個Redux模塊以實(shí)現(xiàn)對遠(yuǎn)程及本地?cái)?shù)據(jù)的獲取、存儲以及檢索。其UI由數(shù)百種React組件實(shí)現(xiàn),其分別負(fù)責(zé)進(jìn)行文本渲染、虛擬列表管理、延遲加載模塊處理以及延遲渲染等任務(wù)。Twitter Lite支持42種語言,我們還利用Globalize為其提供本地化數(shù)字、日期以及消息格式。
為性能而生
每個月,都有上億用戶訪問mobile.twitter.com網(wǎng)站。我們希望Twitter Lite能夠成為解決連接速度緩慢、可靠性差、性能受限或者高成本情況下的最佳Twitter使用途徑。我們得以在其中引入一系列增量性能改進(jìn)(我們將其稱為PRPL模式),同時充分運(yùn)用Android平臺之上各類現(xiàn)代瀏覽器(例如谷歌Chrome)中的各項(xiàng)新功能,具體包括Service Worker、IndexedDB、Web App Install Banners以及Web推送通知等。
可用性保障
Twitter Lite具備網(wǎng)絡(luò)彈性。為了與世界范圍內(nèi)的每一位用戶順暢對接,我們往往需要考慮網(wǎng)絡(luò)速度緩慢且不可靠的情況。在可用性方面,無論具體網(wǎng)絡(luò)狀況如何,我們都會利用Service Worker確保臨時性離線瀏覽與重復(fù)訪問內(nèi)容的近實(shí)時加載效果。Service Worker負(fù)責(zé)對HTML應(yīng)用程序shell與靜態(tài)資產(chǎn)進(jìn)行緩存,其中亦將包含部分常用emoji表情。當(dāng)腳本或者數(shù)據(jù)出現(xiàn)加載失敗時,我們提供“重試”按鈕以幫助用戶從故障中快速恢復(fù)。總而言之,這些變更能夠共同提升可靠性,并在訪問重復(fù)內(nèi)容時顯著加快加載與啟動時間。
漸進(jìn)式加載
Twitter Lite具備漸進(jìn)式特性,能夠在大多數(shù)設(shè)備上立足3G網(wǎng)絡(luò)于5秒內(nèi)完成加載。目前全球大部分地區(qū)仍在使用2G或者3G網(wǎng)絡(luò); 因此快速的初始體驗(yàn)可謂至關(guān)重要。在過去3個月當(dāng)中,我們將平均加載時間縮短了超過30%,且99%的交互時延遲縮短了25%。為了實(shí)現(xiàn)這項(xiàng)目標(biāo),應(yīng)用數(shù)據(jù)流會首先在瀏覽器上進(jìn)行HTML響應(yīng)初始化、將指令發(fā)送至預(yù)加載的關(guān)鍵性資源處,同時由服務(wù)器端進(jìn)行應(yīng)用程序狀態(tài)初始化。利用webpack,應(yīng)用中各腳本將進(jìn)行進(jìn)一步拆分并按需求加載。這意味著初始加載操作只需要當(dāng)前屏幕顯示內(nèi)容所涉及的部分資源。(在可用性方面,Service Worker會對其它資源進(jìn)行預(yù)緩存,從而支持其它屏幕顯示內(nèi)容的即時導(dǎo)航效果。)這些變更使得我們能夠?qū)崿F(xiàn)應(yīng)用的漸進(jìn)式加載,以確保用戶能夠更快查閱及發(fā)布推文。
渲染
Twitter Lite對資源占用率較高的渲染工作進(jìn)行拆分。雖然我們以往一直高度關(guān)注組件渲染流程的優(yōu)化,但推文本身就是一項(xiàng)復(fù)雜的綜合性組件,因此對無數(shù)推文列表進(jìn)行渲染顯然需要進(jìn)行額外的性能考量。我們構(gòu)建起了自己的虛擬化列表組件; 其能夠保證內(nèi)容僅在當(dāng)前視圖內(nèi)可見,同時利用requestAnimationFrame API漸進(jìn)式渲染多個幀上的條目,且保留屏幕上的滾動位置。通過使用requestIdleCallback API將對非關(guān)鍵呈現(xiàn)內(nèi)容的渲染工作推遲至空閑時段,我們成功地進(jìn)一步提升了使用過程中的性能感受。
數(shù)據(jù)使用情況
Twitter Lite會在默認(rèn)情況下減少數(shù)據(jù)使用量,提供體積較小的媒體資源并高度依賴緩存數(shù)據(jù)。我們對于圖像進(jìn)行了優(yōu)化,以確保時間軸滾動操作對數(shù)據(jù)使用量的影響最多降低40%。“數(shù)據(jù)節(jié)約”模式能夠進(jìn)一步減少數(shù)據(jù)使用量,并通過使用體積更小的模糊預(yù)覽圖替換推文與Direct Messages中的圖像。圖像的HEAD請求能夠幫助我們在按鈕旁顯示其具體大小,以便按需進(jìn)行加載。作為體積僅為我們原生應(yīng)用1%到3%大小的應(yīng)用方案,Twitter Lite亦可以大大節(jié)約運(yùn)行所需要的設(shè)備存儲空間。
設(shè)計(jì)系統(tǒng)與迭代速度
提升迭代速度有助于我們始終保持高水平的用戶體驗(yàn)。我們在很大程度上依賴于flexbox布局,同時采用一整套小巧且數(shù)量固定的本色、字體大小與長度設(shè)計(jì)規(guī)范。Twitter Lite由基于組件的響應(yīng)設(shè)計(jì)系統(tǒng)進(jìn)行構(gòu)建,意味著該應(yīng)用能夠符合任何呈現(xiàn)形式。在UI組件的幫助下,我們建立起設(shè)計(jì)與工程技術(shù)團(tuán)體間的共享表達(dá)詞匯,鼓勵雙方能力協(xié)作以實(shí)現(xiàn)快速迭代并復(fù)用現(xiàn)有構(gòu)建單元。我們當(dāng)前最為復(fù)雜的部分功能,例如混合內(nèi)容時間軸,已經(jīng)能夠利用30行代碼完成從配置到接入Redux模塊再到匹配React組件的整個創(chuàng)建流程。
展望未來
立足龐大的用戶群體,構(gòu)建這樣一款快速高效且極具規(guī)模化水平的Web應(yīng)用程序無疑給Twitter公司的設(shè)計(jì)、產(chǎn)品與工程研發(fā)團(tuán)隊(duì)帶來了巨大挑戰(zhàn)。我們對于自身取得的成績感到振奮,并嘗試?yán)肏TTP/2、GraphQL以及多種替代性壓縮格式以進(jìn)一步降低加載時間與數(shù)據(jù)使用量。在未來的幾個月中,我們還將對Twitter Lite的輔助功能、安全性、設(shè)計(jì)、功能以及性能作出更多細(xì)節(jié)改進(jìn)。
查看原文鏈接:How we built Twitter Lite