html5手機Web單頁應用實踐--起點移動閱讀

池中物willian發表於2014-05-07

一開始以hybrid形式做了一個android的小說閱讀客戶端,叫4G閱讀。而後由於業務需求,要迅速實現純手機html5 版的,所以就直接在原先客戶端內內嵌的網頁進行改版,快速實現以後在優化的過程中發現越改越多越改越多…

注意此web應用只支援android及iphone內的瀏覽器,及PC或mac上的chrome,safari,firefox等支援html5的瀏覽器。IE10以上瀏覽器

這算是試驗版了吧,以前沒這麼弄過..

手機訪問http://crapi.4gshu.com:8096/4g-read-qd/#index

先上圖,有圖有真像


檔案結構及路由


 


 

HTML


 

Index.html

整個應用框架的基礎,包含了頭部,尾部HTML,及主要各個頁面部分的容器(content-panel)

根據hash路由通過ajax方式載入對應的內容頁再新增到對應的comtent-panel內

以下是主要內容模組(內容為html片段)

Index-c.html逛

Category-c.html分類

Rank-c.htm排行

Discovery-c.html發現

Channel-c.html男頻,女頻...

Search-c.html搜尋

Bookshelf-c.html書架

Catalog-c.html 目錄

 


 

CSS


 

編寫css時使用了less,特別是在修改時,尤其的好用

Public.css 包含了大部分的應用樣式

Idangerous.swiper.css 切換外掛的樣式檔案

內容頁的樣式可以在自身頁面內自行新增


 

 Javascript


 

Avalon.js 

在此處用這個MV*框架,主要是方便處理將json資料渲染到DOM上

Jquery.js 

很想使用zepto之類的輕DOM框架,但最終還是選擇了jquery2.0,原因是方便擴充套件外掛,很多外掛不相容zepto,其實JS檔案的大小遠沒有你想象的那麼影響web應用的表現,其實css的渲染影響更大,血的教訓啊。關於JS檔案過大的問題,其實應用基本上是在3G或wifi情況下使用,你非要在2G環境下使用,那幹麻不用WAP版...

Idangerous.swiper.js

非常強大的輪播外掛,其實可以實現很多東西。所以選用它來實現輪播

Mango-decoupling.js

很好用的訊息外掛,用於程式中解耦設計,其訊息機制也非常強大

Config.js

由於將這個應用分發到不同的渠道,而不同渠道又有一些不同的配置需求,所以用了config.js來配置一些屬性

Core.js

整個框架通用JS的核心,包含了本地儲存,通訊,通用的事件與方法

 

為了方便實現,及減少JS檔案數,各個內容模組的JS業務邏輯都直接寫在各自的html片段中。內容模組在渲染完畢後應該向框架傳送一個渲染完畢的訊息,或執行框架提開放的渲染完畢API,比如“page_ready”,方便框架處理loading等全域性的控制


 

本地儲存


 

1、離線儲存cloudary.appcache,儘可能的將css,js,image,及HTML程式碼片段檔案都離線儲存至本地。初次訪問時會將所有相關檔案都離線到本地,以後再次訪問,會優先讀取離線到本地的檔案

2、Localstorage儲存介面資料。開發過程中明顯感覺到,後臺提供的資料介面的速度明顯影響了整個應用的表現,所以在初次訪問動態資料介面時將使用localstorage將整個介面返回的資料儲存到本地,以後再次訪問時先優先讀取本地的資料,然後後臺會靜默更新資料到localstorage內,由於應用沒有那麼高的實時性要求,所以此方案可行。


Hash路由


 

整個應用的內容模組content-panel其實是由hash路由來連起來的,構成了所謂的單面應用,即不重新整理整個頁面。一開始使用的是popstate來實現,結果發現在chrome瀏覽器下一進頁面就會觸發一次popstate事件,比較奇葩,這個問題是在應用完成後發現的,還好popstate事件是在core.js中進行過封裝的,我就在封裝處將popstate事件替換成了hashchange事件,所以說對外部的API還是要抱有不信任的態度,儘量進行封裝分隔,萬一發生改變,改起來也快。在載入不同的內容模組時,通過wndow.history的pushState和replaceState來實現hash值的改變,在一進頁面時首先得把自身頁面進行一次replaceState,將自身加入history佇列,否則history佇列會亂(一大坑啊,反正我以前沒replaceState時是遇到過,怎麼也管理不好佇列)。

根據UI上的設計及功能的不同,我將路由分成了兩類,

主頁路由:

Index 逛

Category分類

Rank 排行

Discovery 發現

子頁路由:

Channel頻道

category-detail 分類詳情

Topic 專題

Detail 詳情

Search 搜尋

Bookshelf 書架

Catalog 目錄


關於路由的速度優化


 

1、很多內容模組開啟過一次後再次開啟時完全是不用再請求的,所以得判斷是否開啟過,開啟過的應用再次開啟時就不再請求對應的html片段了,直接顯示之前請求下來的html片段,比如index,category,rank,discovery,topic,bookshelf,search這幾個內容模組

 

2、對於需要更新內容的模組,比如detail,channel模組,第一次請求到html片段後也可以快取下來,以後每次請求新的內容時只需要通過JSON資料更新dom即可,即無需把dom清掉再重新建立新dom。這一點的優化對於效能比較差的mobile裝置上尤其重要,這樣實現後,請求資料這個動作需要在路由發生變化時傳送自定義訊息(如:refresh_with_new_data),接受到自定義訊息時再傳送資料請求,得到訊息後再更新dom的內容。

 

3、即使對於需要更新的內容,同一個連結,連續被開啟時,由於資料完全沒有變化,所以也可以完全不去請求資料,即可做到所謂的“秒開”

 


理論上應該用但並未使用的技術


 

1、backbone,算是比較廣泛的mvc框架了,自身提供了路由功能,但個人覺得需要寫的程式碼量太大,如果是團隊使用用來規範程式碼還行,如果個人使用的話,我覺得還是太重了。寫一個簡單的功能就一大堆程式碼及對應的JS檔案。 

2、Requirejs或seajs

本身應用中就首頁這幾個JS檔案,寫完就沒了,沒必要再多一個額外的JS檔案請求

3、一些新的CSS3屬性

某些比較好用的CSS3屬性在移動端支援有限,所以沒有使用,比如佈局的兩端對齊

4、較高的內容模組分段顯示,即滾動到了後再渲染到DOM中,首先後臺並未提供分斷載入的API,其次,自適應的佈局加大了實現的難度,最後,木有足夠的時間


不足


 

1、開發時間過短,很多公司的通病吧

2、產品在設計時未考慮單頁應用的場景,層級太深的頁現在還是重新整理整個頁面

3、有些功能還未按以上的構架實現,比如動態介面本地儲存只做了index首頁等

4、比較醜,樣子醜,程式碼實現也比膠水

 


 

No zuo no die


 

為何在內容模組切換過程中未新增一些像native應用切換一樣的動畫效果?

由於android的機型無花八門,效能參差不齊,css3動畫支援力度不一,很多hybrid應用的出現正是為了彌補這樣的缺點。佈局用html,切換動畫使用native。如果你的web應用只要求跑在iphone這等高大上的裝置上的話,完全可以使用css3來實現介面切換動畫,如果你要求跑在所有平臺上,那麼......該吃藥了親..

如果你非要嘗試,那麼你應該會體會到什麼叫no zuo no die

 


 結束語


 

優化工作是個系統性工程,得從方方面面考慮,從產品設計--》UI設計--》前端程式碼實現--》後臺資料介面提供

現在的優化只能算是皮毛吧,不僅前端部分需要優化,而且後臺資料介面速度過慢也嚴重導致了響應速度。

純粹的手機web單頁應用本來就做的比較少,經驗太少,需要繼續努力學習..

碼農啊...

有看到這篇文章的同學歡迎提意見,優化方面特別是

======================================================== 

轉載處請註明:部落格園(王二狗)willian12345@126.com

 

 

 

相關文章