不論是第一次使用 FineUI 控件庫的網友,仍是有着 3 年以上使用經驗的網友,都對 FineUI 的簡單印象深入。固然,「一切爲了簡單」也是 FineUI 一句響亮的口號,不只如此,一個開源項目要想立足並長久發展下去,光憑着簡單是不行,還要有本身的特點,這個特點就是創新。php
從 FineUI 的官網(http://fineui.com/)咱們明顯看到 FineUI 的三個大特性「一切爲了簡單」、「用心實現80%的功能」、「創新因此獨一無二」:html
而今天要講的就是「創新」的範疇。git
咱們都知道 ViewState 是 ASP.NET WebForms 的一個重要的基礎,用來在頁面回發過程當中維護控件的服務器端狀態,這樣咱們就能方便的在回發事件處理函數中隨意使用控件屬性了,好比下面代碼:瀏覽器
1: Label1.Text = TextBox1.Text;
可是在 AJAX 的應用環境中,ViewState 會代碼下載數據的冗餘,因此 FineUI 很早就在其內部實現了適合 AJAX 的 XState 機制,從而減小下載數據的冗餘,加快頁面的呈現速度。服務器
可是請注意,FineUI 使用 XState 並不是啓用 ViewState,傳統的 ASP.NET 控件仍然使用 ViewState,你們也仍然能夠在 ViewState 中保存少許的數據,好比以下代碼依然有效:網絡
1: if (ViewState["BindGrid1"] != null && Convert.ToBoolean(ViewState["BindGrid1"]))
2: {
3: BindGrid();
4: ViewState["BindGrid1"] = false;
5: }
以前有一篇詳細的文章來對比 ViewState 和 XState 對使用 FineUI 控件庫的印象:http://www.cnblogs.com/sanshi/archive/2013/01/08/2850459.htmlide
這裏咱們簡單把結論列一下:函數
對於以下這個頁面,咱們分別比較頁面第一次加載和點擊按鈕回發兩個過程當中下載的數據量:性能
使用 ViewState 的版本: 第一次頁面加載下載數據(5068 bytes) 點擊按鈕回發下載數據(1251 bytes)測試
使用 XState 的版本: 第一次頁面加載下載數據(4922 bytes) 點擊按鈕回發下載數據(709 bytes)
可見,XState 帶來了一個很大的優點,那就是減小數據的下載量。
以前一直很關心數據下載量,而忽視了數據上傳量。其實咱們所處的網絡環境是一個上行下行不對稱的網絡,通常上行速度是下行速度的 1/2,甚至更少。來引用一篇文章中的一段:
Why Upload and Download Speeds Differ
Upload speed is usually slower than download speed because Internet providers have designed their systems to optimize download speeds. This is because most Internet users spend more time downloading than uploading. In other words, Internet providers give priority to downloading since it's more frequently done than uploading.
換句話說,由於人們對下載的需求更旺盛,因此網絡提供商通常會分配給下載更高的傳輸速度。
我一直沒有向這個方向考慮,直到有論壇網友提出了這個問題:http://fineui.com/bbs/forum.php?mod=viewthread&tid=3166
看到這篇帖子的時候,我就意識到了,FineUI 是作出改變的時候了!
由於咱們須要在服務器和客戶端以前持久化數據,對於這個網友的例子而言,就是表格中那些已經渲染後的HTML代碼。通用的辦法就是對客戶端提交的數據進行壓縮,可是在客戶端使用 JavaScript 實現相似 Gzip 的壓縮簡直就是天方夜譚(瀏覽器性能受不了)!
怎麼辦?
既然沒法在客戶端進行壓縮,就只好在服務器端進行壓縮了。因此思路以下:
1. 在頁面加載時在服務器端壓縮須要持久化的狀態,並寫入頁面中;
2. 下載 AJAX 提交時,提交壓縮後的持久化數據;
3. 在 AJAX 提交過程當中,從新生成新的壓縮後的持久化數據,並寫入頁面中;
4. 如此下去….
基於以下幾點考慮,這部分新增的壓縮數據不會對下載量形成很大的影響:
1. 下行帶寬通常都比較充足;
2. 通過壓縮後的持久化數據通常比較小;
3. 下載數據通常都會通過 GZIP 壓縮。
具體到 FineUI 中的實現,也很簡單,首先定義 GZIP 壓縮和解壓函數:
1: public static string Gzipped(string source)
2: {
3: using (var outStream = new MemoryStream())
4: {
5: using (var gzipStream = new GZipStream(outStream, CompressionMode.Compress))
6: {
7: using (var mStream = new MemoryStream(Encoding.UTF8.GetBytes(source)))
8: {
9: mStream.WriteTo(gzipStream);
10: }
11: }
12:
13: return StringUtil.EncodeTo64(outStream.ToArray());
14: }
15: }
16:
17: public static string Ungzipped(string source)
18: {
19: byte[] bytes = Convert.FromBase64String(source);
20:
21: using (GZipStream stream = new GZipStream(new MemoryStream(bytes), CompressionMode.Decompress))
22: {
23: const int size = 512;
24: byte[] buffer = new byte[size];
25: using (MemoryStream memory = new MemoryStream())
26: {
27: int count = 0;
28: do
29: {
30: count = stream.Read(buffer, 0, size);
31: if (count > 0)
32: {
33: memory.Write(buffer, 0, count);
34: }
35: } while (count > 0);
36:
37: return System.Text.Encoding.UTF8.GetString(memory.ToArray());
38: }
39: }
40: }
而後爲控件基類添加一個須要對哪些屬性進行 GZIP 壓縮的屬性:
1: private List<string> _gzippedAjaxProperties = new List<string>();
2:
3: internal List<string> GzippedAjaxProperties
4: {
5: get { return _gzippedAjaxProperties; }
6: set { _gzippedAjaxProperties = value; }
7: }
最後,在頁面第一次加載和 AJAX 過程當中壓縮這個屬性:
1: bool propertyGzippped = _gzippedAjaxProperties.Contains(property);
2: string propertyGzippedValue = String.Empty;
3:
4: object propertyValue = GetPropertyJSONValue(property);
5:
6: JToken tokenValue = propertyValue as JToken;
7: jo.Add(property, tokenValue);
8:
9: if (propertyGzippped)
10: {
11: propertyGzippedValue = tokenValue.ToString(Newtonsoft.Json.Formatting.None);
12: }
13:
14: if (propertyGzippped && !String.IsNullOrEmpty(propertyGzippedValue))
15: {
16: jo.Add(property + "_GZ", StringUtil.Gzipped( propertyGzippedValue));
17: }
爲了進行測試,咱們建立了一個表格頁面,頁面效果以下:
這個頁面總共有 22 行數據,咱們來比較頁面第一次加載和點擊「選中了哪些行」兩個操做在優化先後的結果。
優化前,頁面第一次加載(UP:0 DOWN:30684):
優化前,頁面回發(UP:33202 DOWN:186):
優化後,頁面第一次加載(UP:0 DOWN:34366):
優化後,頁面回發(UP:6016 DOWN:186):
通過優化後,頁面第一次加載時下載數據由 30684 bytes 增長爲 34366 bytes,增長了 12%,而這個增長量不會對下載形成多大的影響。
而上傳量卻有大幅減小,AJAX 回發時上傳數據由原來的 33202 bytes 減小爲 6016,減小了 82%,對於上行帶寬不足的現實,這個改變帶來的影響確實巨大的!
優化後的 FineUI 控件庫會稍微增長下載數據量,可是考慮到下行帶寬通常比較充裕,而且下行數據通常會通過 GZIP 壓縮,因此這個改變影響不大。現實的好處是上傳數據大幅減小了 80%,這個改變帶來的影響確實巨大的!
注:這個特性會加 FineUI 下個版本中去(FineUI v3.3.1)。
喜歡這篇文章,就不要忘記點擊頁面右下角的【推薦】按鈕哦。