標籤:本地 com back ddc 種類 緩衝機制 github 終端 html5
讓我們先來看幾個網站:
coding(https://coding.net/)
teambition(https://www.teambition.com/)
cloud9(https://c9.io/)
?
注意這幾個網站的相同點。那就是在瀏覽器中,做了原先“應當”在client做的事情。
它們的介面切換非常流暢,響應非常迅速,跟傳統的網頁明顯不一樣,它們是什麼呢?這就是單頁Web應用。
所謂單頁應用。指的是在一個頁面上整合多種功能。甚至整個系統就僅僅有一個頁面,全部的業務功能都是它的子模組,通過特定的方式掛接到主介面上。
它是AJAX技術的進一步升華。把AJAX的無重新整理機制發揮到極致,因此能造就與傳統型程式媲美的流暢使用者體驗。
事實上單頁應用我們並不陌生,非常多人寫過ExtJS的項目。用它實現的系統。非常天然的就已經是單頁的了。也有人用jQuery或者其它架構實現過相似的東西。
用各種JS架構。甚至不用架構。都是能夠實現單頁應用的。它僅僅是一種理念。有些架構適用於開發這種系統。假設使用它們,能夠得到非常多便利。
開發架構
ExtJS能夠稱為第一代單頁應用程式框架的典型,它封裝了各種UI組件。使用者主要使用JavaScript來完畢整個前端部分,甚至包含布局。
隨著功能逐漸添加,ExtJS的體積也逐漸增大。即使用於內部系統的開發。有時候也顯得笨重了,更不用說開發以上這類執行在互連網上的系統。
jQuery由於偏重DOM操作。它的外掛程式體系又比較鬆散。所以比ExtJS這個體系更適合開發在公網執行的單頁系統,整個解決方式會相對照較輕量、靈活。
但由於jQuery主要面向上層操作,它對代碼的組織是缺乏約束的。如何在代碼急劇膨脹的情況下控制每一個模組的內聚性。而且適當在模組之間產生資料傳遞與共用。就成為了一種有挑戰的事情。
為瞭解決單頁應用規模增大時候的代碼邏輯問題,出現了不少MV*架構。他們的基本思路都是在JS層建立模組分層和通訊機制。
有的是MVC,有的是MVP。有的是MVVM。而且,它們差點兒都在這些模式上產生了變異。以適應前端開發的特點。
這類架構套件含Backbone。Knockout,AngularJS,Avalon等。
組件化
這些在前端做分層的架構推動了代碼的組件化,所謂組件化,在傳統的Web產品中,很多其它的指UI組件,但事實上組件是一個廣泛概念。傳統Web產品中UI組件佔比高的原因是它的厚度不足,隨著client代碼比例的添加,相當一部分的商務邏輯也前端化,由此催生了非常多非介面型組件的出現。
分層帶來的一個優勢是,每層的職責更專一了,由此,能夠對其作單元測試的覆蓋,以保證其品質。
傳統UI層測試最頭疼的問題是UI層和邏輯混雜在一起,比方往往會在遠程請求的回調中更改DOM,當引入分層之後。這些東西都能夠分別被測試,然後再通過情境測試來保證總體流程。
代碼隔離
與開發傳統頁面型網站相比,實現單頁應用的過程中,有一些比較值得特別關注的點。
從單頁應用的特點來看。它比頁面型網站更加依賴於JavaScript,而由於頁面的單頁化,各種子功能的JavaScript代碼聚集到了同一個範圍,所以代碼的隔離、模組化變得非常重要。
在單頁應用中。頁面模板的使用是非常普遍的。非常多架構內建了特定的模板,也有的架構須要引入第三方的模板。這種模板是介面片段,我們能夠把它們類比成JavaScript模組,它們是還有一種類型的組件。
模板也一樣有隔離的須要。不隔離模板,會造成什麼問題呢?模板間的衝突主要存在於id屬性上,假設一個模板中包含固定的id。當它被批量渲染的時候。會造成同一個頁面的範圍中出現多個相同id的元素。產生不可預測的後果。因此。我們須要在模板中避免使用id,假設有對DOM的訪問需求。應當通過其它選取器來完畢。假設一個單頁應用的組件化程度非常高,非常可能整個應用中都沒有元素id的使用。
代碼合并與載入策略
人們對於單頁系統的載入時間容忍度與Web頁面不同,假設說他們願意為購物頁面的載入等待3秒,有可能會願意為單頁應用的首次載入等待5-10秒,但在此之後,各種功能的使用應當都比較流暢,全部子功能頁面盡量要在1-2秒時間內切換成功,否則他們就會感覺這個系統非常慢。
從這些特點來看,我們能夠把很多其它的公用功能放到首次載入,以減小每次載入的載入量,有一些網站甚至把全部的介面和邏輯全部放到首頁載入,每次業務介面切換的時候,僅僅產生資料請求,因此它的響應是非常迅速的。比方青雲的控制台就是這麼做的。
通常在單頁應用中,無需像網站型產品一樣,為了防止檔案載入堵塞渲染,把js放到html後面載入。由於它的介面基本都是動態產生的。
當切換功能的時候,除了產生資料請求。還須要渲染介面,這個新渲染的介面組件通常是介面模板,它從哪裡來呢?來源無非是兩種,一種是即時請求,像請求資料那樣通過AJAX擷取過來。還有一種是內建於主介面的某些位置。比方script標籤或者不可見的textarea中,後者在切換功能的時候速度有優勢,可是加重了首頁面的負擔。
在傳統的頁面型網站中,頁面之間是互相隔離的,因此。假設在頁面間存在可複用的代碼,通常是提取成單獨的檔案,而且可能會須要依照每一個頁面的需求去進行合并。單頁應用中,假設總的代碼量不大,能夠總體打包一次在首頁載入。假設大到一定規模,再作執行時載入,載入的粒度能夠搞得比較大。不同的塊之間沒有反覆部分。
路由與狀態的管理
我們最開始看到的幾個線上應用,有的是對路由作了管理的,有的沒有。
管理路由的目的是什麼呢?是為了能降低使用者的導航成本。比方說我們有一個功能。經曆過多次導覽功能表的點擊,才呈現出來。
假設使用者想要把這個功能地址分享給別人,他怎麼才幹做到呢?
傳統的頁面型產品是不存在這個問題的。由於它就是以頁面為單位的。也有的時候,服務端路由處理了這一切。可是在單頁應用中,這成為了問題,由於我們僅僅有一個頁面,介面上的各種功能區塊是動態產生的。所以我們要通過對路由的管理,來實現這種功能。
詳細的做法就是把產品功能劃分為若干狀態,每一個狀態映射到相應的路由,然後通過pushState這種機制,動態解析路由,使之與功能介面匹配。
有了路由之後,我們的單頁面產品就能夠前進後退,就像是在不同頁面之間一樣。
事實上在Web產品之外,早就有了管理路由的技術方案。Adobe Flex中。就會把比方TabNavigator。甚至下拉框的選中狀態相應到url上。由於它也是單“頁面”的產品模式。須要面對相同的問題。
當產品狀態複雜到一定程度的時候,路由又變得非常難應用了,由於狀態的管理極其麻煩,比方開始的時候我們示範的c9.io線上IDE,它就沒法把狀態相應到url上。
緩衝與本機存放區
在單頁應用的運作機制中。緩衝是一個非常重要的環節。
由於這類系統的前端部分差點兒全是靜態檔案。所以它能夠有機會利用瀏覽器的緩衝機制,而比方動態載入的介面模板,也全然能夠做一些自己定義的緩衝機制。在非首次的請求中直接取緩衝的版本號碼,以加快載入速度。
甚至,也出現了一些方案,在動態載入JavaScript代碼的同一時候,把它們也緩衝起來。比方Addy Osmani的這個basket.js。就利用了HTML5 localStorage作了js和css檔案的緩衝。
在單頁產品中,業務代碼也經常會須要跟本機存放區打交道,儲存一些暫時資料。能夠使用localStorage或者localStorageDB來簡化自己的業務代碼。
服務端通訊
傳統的Web產品通常使用JSONP或者AJAX這種方式與服務端通訊,但在單頁Web應用中。有非常大一部分採用WebSocket這種即時通訊方式。
WebSocket與傳統基於HTTP的通訊機制相比,有非常大的優勢。
它能夠讓服務端非常便利地使用反向推送,前端僅僅響應確實產生業務資料的事件。降低一遍又一遍無意義的AJAX輪詢。
由於WebSocket僅僅在比較先進的瀏覽器上被支援,有一些庫提供了在不同瀏覽器中的相容方案。比方socket.io,它在不支援WebSocket的瀏覽器上會降級成使用AJAX或JSONP等方式,對業務代碼全然透明、相容。
記憶體管理
傳統的Web頁面通常是不須要考慮記憶體的管理的。由於使用者的停留時間相對少,即使出現記憶體流失。可能非常快就被重新整理頁面之類的操作衝掉了,但單頁應用是不同的。它的使用者非常可能會把它開一整天。因此。我們須要對當中的DOM操作、網路連接等部分格外小心。
樣式的規劃
在單頁應用中。由於頁面的整合度高。全部頁面聚集到同一範圍,樣式的規劃也變得重要了。
樣式規劃主要是幾個方面:
根據樣式的分離
這裡面主要包含瀏覽器樣式的重設、全域字型的設定、布局的基本約定和響應式支援。
組件樣式的劃分
這裡面是兩個層面的規劃,首先是各種介面組件及其子項目的樣式。其次是一些修飾樣式。組件樣式應當盡量降低互相依賴,各組件的樣式同意冗餘。
堆疊次序的管理
傳統Web頁面的特點是元素多。可是層次少,單頁應用會有些不同。
在單頁應用中,須要提前為各種UI組件規劃堆疊次序。也就是z-index,比方說,我們可能會有各種彈出對話方塊,浮動層,它們可能組合成各種堆疊狀態。新的對話方塊的z-index須要比舊的高,才幹確保蓋在它上面。諸如此類,都須要我們對這些可能的遮蓋作規劃。那麼,如何去規劃呢?
瞭解通訊知識的人,應當會知道,不同的頻率段被劃分給不同的通訊方式使用,在一些國家,領空的使用也是有劃分的。我們也能夠用相同的方式來預先分段,不同類型的組件的z-index落到各自的區間。以避免它們的衝突。
單頁應用的產品形態
我們在開始的時候提到,存在著非常多新型Web產品,使用單頁應用的方式構建,但實際上,這類產品不僅僅存在於Web上。
點開Chrome商店,我們會發現非常多離線應用。這些產品都能夠算是單頁應用的體現。
除了各種瀏覽器外掛程式。藉助node-webkit這種外殼平台。我們能夠使用Web技術來構建本地應用,產品的主要部分仍然是我們熟悉的單頁應用。
單頁應用的流行程度正在逐漸添加。大家假設關注了一些初創型互連網企業。會發現當中非常大一部分的產品模式是單頁化的。這種模式能帶給使用者流暢的體驗,在開發階段。對JavaScript技能水平要求較高。
單頁應用開發過程中,前後端是天然分離的,兩方以API為分界。前端作為服務的消費者,後端作為服務的提供者。在此模式下,前端將會推動後端的服務化。
當後端不再承擔模板渲染、輸出頁面這樣工作的情況下。它能夠更專註於所提供的API的實現,而在這種情況下。Web前端與各種移動終端的地位對等,也逐漸使得後端API不必再為每一個端作差異化設計了。
部署模式的改變
在如今這個時代,我們已經能夠看到一種產品的出現了。那就是“無後端”的Web應用。
這是一種什麼東西呢?基於這種理念。你的產品非常可能僅僅須要自己編寫靜態Web頁面,在某種BaaS(Backend as a Service)雲平台上定製服務端API和雲端儲存,整合這個平台提供的SDK,通過AJAX等方式與之打交道,實現注冊認證、社交、訊息推送、即時通訊、雲端儲存等功能。
我們觀察一下這種模式,會發現前後端的部署已經全然分離了,前端代碼全然靜態化,這意味著能夠把它們放置到CDN上,訪問將大大地加速。而服務端託管在BaaS雲上。開發人員也不必去關注一些部署方面的繁瑣細節。
假設你是一名創業者。正在做的是一種即時協同的單頁產品,能夠在雲平台上,高速定製後端服務。把絕大部分寶貴的時間花在開發產品本身上。
單頁應用的缺陷
單頁應用最根本的缺陷就是不利於SEO,由於介面的絕大部分都是動態產生的,所以搜尋引擎非常不easy索引它。
產品單頁化帶來的挑戰
一個產品想要單頁化。首先是它必須適合單頁的形態。
其次,在這個過程中。對開發模式會產生一些變更,對開發技能也會有一些要求。
開發人員的JavaScript技能必須過關,同一時候須要對組件化、設計模式有所認識,他所面對的不再是一個簡單的頁面,而是一個執行在瀏覽器環境中的案頭軟體。
原文地址:https://github.com/xufei/blog/issues/5
構建單頁Web應用