有幸做爲講師受邀參加InfoQ在上海舉辦的QCon2017,不得不說,不管是從講師仍是聽衆的角度衡量,QCon進一步擴大了技術視野。雖然前端專題只有四場,但每一場分享都是目前的熱門話題。而且Qcon的選題都是從實踐出發,並無一些看起來很炫可是還沒有通過實踐檢驗的新技術,即便是目前剛剛起步且相對來講比較小衆的WebAssembly也是以餓了麼的生產實踐爲基礎。css
個人分享話題是《面向SPA和Hybrid應用的前端工程體系和實踐經驗》,從我我的角度來說仍是缺少演講技巧,語速過快致使比預期的時間提早了將近1/3,爲聽衆爭取到了一個比較長的茶歇時間╮(╯▽╰)╭。演講結束後與支付寶的同行探討了一些相關的問題,挖掘了目前搜狗地圖團隊從工程角度的一些不足和啓發,好比模板更新率以及解析速度提高等。可是與支付寶業務不一樣的是,搜狗地圖中對於模板的定義並非「離線包」,而是一種相似於html模板的動態解析「引擎」。html
分享的現場在正式進入話題前與現場的聽衆進行了一次小小的互動:粗略統計了一下當時在場的人當中搜狗地圖的用戶比例。尷尬的是,除了出品人@winter老師礙於面子舉起了手之外,現場並無第三個搜狗地圖用戶(我是第二個╮(╯▽╰)╭)。固然,這也算是意料之中,搜狗地圖雖然國內的市場佔有率並不高,甚至我在QCon講師微信羣裏打招呼後有位老師居然問「搜狗開始作地圖了?」。「開始」這個詞用的真是很尷尬啊,那麼我就先科普一下搜狗地圖的歷史吧。前端
搜狗地圖前身是圖行天下,成立於1999年,是國內第一家互聯網地圖服務網站,2005年被搜狐收購後更名爲「搜狗地圖」。因此這個剛「開始」作的地圖產品比大多數人預料的還要老。講歷史主要不是爲了科普,也不是倚老賣老,而是從側面闡明咱們在進行工程化改造時所面臨的項目特徵:一個有着近20年曆史包袱、模塊結構混亂的「老傢伙」(PS:搜狗地圖目前的pc web地圖能夠完美兼容IE5╮(╯▽╰)╭)。這樣的老項目不可能短期內切換到全新的技術棧,也不可能大膽地使用一些比較潮的技術和框架,更多的是從策略的角度進行優化。因此我分享內容更加貼近於經驗而不是技術自己,相比較其餘三位的話題,我所分享內容的方方面面幾乎是每一個人都熟悉的,咱們的工做即是綜合這些成熟且穩定的「常識技術」進行工程優化。web
前端工程體系並非一個固有名詞,每一個團隊因爲組織、業務以及架構上的不一樣,對於前端工程體系的理解的也不盡相同。在進入正題以前必須區分的兩個概念是:工程化與工程體系。工程化是一個動詞,意指將業務項目進行工程改造,好比合理的模塊化、先後分離等等;而工程體系是一個名詞,能夠理解爲工程化的外在表現以及輔助框架,好比構建、測試、部署等等。搜狗地圖前端團隊對前端工程體系的理解是:工程體系本質上是一種服務,其服務的對象是技術團隊所採用的技術以及組織架構。而架構自己也定位爲一種服務,其服務的對象是具體的業務。因此在這一層三角關係之中,業務是決定全部服務的核心和出發點。咱們常常將的一句話是:技術不能脫離業務。我也但願這句話可以成爲每個技術開發者和決策者的座右銘。
後端
從業務出發進行工程優化的第一步是提煉業務特徵,從而選擇合理的技術和組織架構。咱們從四個方面提取業務特徵:場景、類型、設備以及平臺。
瀏覽器
以Web地圖業務爲例,從進入頁面到展現完整地圖的工做流程大體以下:
緩存
地圖能夠說是將按需加載發揮到極致的最佳實踐業務。你們能夠想象一下,以街道爲維度將北京市的全貌繪製到瀏覽器中,瀏覽器可否承載如此大的工做量?即便拋開技術的侷限性,單純從需求的角度來說,用戶一般只須要查看以當前位置或者搜索位置爲中心的有限區域內的地圖。因此對於地圖來講,第一步也是最重要即是定位:服務器
精肯定位是很是複雜的功能,感興趣的能夠自行查閱相關資料。微信
除了Web地圖之外,搜狗地圖前端業務的另外一種主要形式是Hybrid。將這兩種業務形式進行概括總結,提取的業務特徵大體以下:
網絡
業務特徵決定技術架構,最終提煉出適用於搜狗地圖前端業務的架構類型即是目前較流行的單頁應用—SPA。
不依賴與服務端渲染的SPA不管是從架構層面,仍是從開發和部署層面都帶來不少便利。HTML文檔能夠做爲一種靜態資源與js、css等一同部署,然而從緩存處理方面,須要單獨處理HTML這種「特殊」的靜態資源。它的特殊之處便在於:HTML是全部其餘靜態資源的入口。
HTML的特殊性決定它不能使用http強制緩存策略,只適用於協商緩存:
這樣能夠保證各種型資源實時性的同時,最大化利用http緩存,對於常規的SPA項目(好比Web地圖)是一種比較普適的方案。然而協商緩存必需要求一次真實有效的http請求以便服務器進行緩存有效性斷定,離線場景下並不適用。而離線是Hybrid應用較廣泛的場景之一,後續會提到如何在協商緩存理念基礎上的優化策略。
搜狗地圖Hybrid架構經歷了三個階段,最初始的方案是:Web多頁項目+多Webview。也就是說,每一個Webview承載一個Web頁面,頁面之間的切換就是Webview之間的切換,頁面之間的通訊即是Webview間的通訊。
這種架構一個最大的問題是:各頁面之間的通訊很是不暢,並且影響用戶體驗。以下所示的是一個很是廣泛的場景:
這種方案存在的致命缺陷在於,pageA並不知道pageB是否提交了表單[注],因此返回pageA後不論pageB操做與否都要進行刷新。不管是從節省流量仍是用戶體驗的角度來說都是負面的。
注:pageA其實有辦法獲取pageB是否進行了提交。一種方案是經過localstorage的storage事件,然而兼容性很是不理想;另外一種方案是經過native提供特定的接口,這種方案雖然兼容性好可是須要客戶端的開發工做。
在上述問題的基礎上進行優化的第一步,是結合SPA架構和Webview自身的緩存機制。
Webview的緩存機制包括如下幾種:
LOAD_CACHE_ONLY
- 不使用網絡,只讀取本地緩存數據LOAD_DEFAULT
- 根據cache-control決定是否從網絡上取數據LOAD_NO_CACHE
- 不使用緩存,只從網絡獲取數據LOAD_CACHE_ELSE_NETWORK
- 只要本地有,不管是否過時,或者no-cache,都使用緩存中的數據其中LOAD_DEFAULT
是最接近常規瀏覽器的緩存機制,在這種模式下,結合上文提到的SPA緩存策略,與常規的Web頁面並沒有二致。然而App並非常規的瀏覽器,其使用場景(手機)的特殊性要求咱們在一些特殊的方面進行優化,好比緩存清理和離線使用。
其中第一條是歷史緣由,公司運維層面將CDN緩存有效期固定位1小時,遷移優化成本較高。http緩存過時後並不會自動清理,之因此常規瀏覽器不用顧忌這個問題是因爲PC設備儲存空間大,而且可使用電腦管家之類的優化軟件手動清理。雖然手機等移動設備的儲存空間也不斷加大,但仍然有至關一部分設備的儲存空間十分感人(我本身用的16G的iphone 7P,感同身受╮(╯▽╰)╭)。若是聽任過時的http緩存無論便會形成app佔用的空間愈來愈大,極端的用戶可能一氣之下就把app卸載了,我本身便曾經在陰陽師和狂野飆車之間作過抉擇,最終卸載了陰陽師╮(╯▽╰)╭。
因此這並非最終合理的方案,可是此次探索給了進一步的優化工做靈感:是否是能夠吸收協商緩存的理念,同時結合Webview自身的緩存機制呢?以此爲方向便產生了目前採用的協商緩存理念的Hybrid模板更新策略。
模板是什麼?前文提到了模板並非靜態的離線包,而是具有動態數據解析功能的邏輯模塊。這個理念來源於SSR(服務端渲染)中的html模板,這應該是前端工程師們再熟悉不過的名詞了,前幾年還沒有實現先後端分離開發時,html模板能夠說是折磨前端工程師的主力之一。
模板以壓縮包的形式傳輸,進入App以後若是處於Wifi環境則會自動檢查並下載最新版本的模板包。而且在App進程運行以及掛起期間不會進行屢次檢查。
具體每一個模板包對應的頁面,進入以後並不會檢查模板包的版本,只要本地存在便展現,不然fallback展現線上的Web URL。這種策略是爲了儘量減小具體業務頁面的解析時間。做爲fallback的Web地址採用WebView的LOAD_DEFAULT
緩存策略,有效期爲CDN緩存(1小時)。另外,若是用戶經過任務管理器手動殺死了App進程,下次進入App以後首先會清理以前殘留的http緩存文件。
綜上,搜狗地圖的前端工程體系簡易架構大體以下:
與常規Web項目的不一樣點在於,地圖項目大量使用SVG和Canvas,組件庫包括二者相關的組件。另外,負責與native通訊的bridageJS是Hybrid應用所特有的。平臺層由Gitlab把關,Webhook觸發自動構建、測試和部署。另外,模板包能夠由開發人員直接部署,不須要通過公司運維,這也是與常規Web項目相比的優點之一。
因爲每一個模板包都會對應一個fallback的Web地址,因此在構建流程中須要針對兩種場景分別構建。模板文件對於App來講其實就是本地文件,因此模板文件中對於其餘文件的引用統一使用相對地址,而且因爲模板自己就是增量的,無需在靜態文件名中加入hash指紋。構建工具備Node.js爲底層平臺,使用特殊的環境變量結合EJS引擎區分構建,以下:
至此即是搜狗地圖目前針對SPA和Hybrid項目的總體工程體系,固然這並非終點,甚至稱不上是最佳實踐。這次分享的目標也並非剖析咱們團隊的工程實踐,更多的是將這一路走來的探索歷程分享給你們,但願可以給一樣面臨老項目改造的團隊一些啓發。
最後簡單提一個優化的案例。模板也是分模塊的,不能將全部的業務集中在一個模板中,不然任何一個微小的修改都會形成整個模板包的更新,並且隨着業務的不斷擴展,模板包的體積愈來愈大,下載和解析時間最終會超過用戶的心理承受界限。因此咱們在模板顆粒度劃分方面作了一些優化:將邏輯無耦合的業務定義爲一個模板包,好比用戶中心與詳情頁,二者除了登陸信息共享之外,幾乎不存在邏輯上的耦合,因此將二者劃分爲兩個模板。在此基礎上將共用的類庫文件提取出來單獨做爲一個模板。
若是讓我給這套工程體系打分可能只達到了60分的及格線,可是對於一個「歷史悠久」的團隊而言,這仍然是很是可觀的「一大步」。後續仍然須要不斷進行優化和迭代,好比會後與支付寶的同窗一塊兒探討的更新率問題。技術的道路遠沒有盡頭,回到一開始的那句話:技術永遠服務於業務。總結此次的QCon之行,我看到了優秀的技術從業者們以實際業務爲中心的探索和務實精神,收穫的不只僅是技術的增加,更重要的是擴寬了眼界。
最後,感謝主辦方InfoQ的邀請,完整PPT下載。