高性能的Ajax應用-Julien Lecomte
第1部分 高性能的開發
1.為高性能計劃和設計
-從每一天開始就要計劃高性能
-跟產品經理和設計師緊密的合作
-理解設計的基本原理
-設計和性能之前做解釋和權衡
-提供選擇和展示各種可能(原型)
-挑戰自己,實現有挑戰性的設計(不要只說「不」)
-為了簡化設計和交互,有時候需要妥協
2.高性能工程開發:一些基本規則
-少就是多。不要做任何不必要的事。直到變得絕對重要,否則不要做。
-打破規則。只能在迫不得以的情況下,才能妥協並打破最佳做法。
-在提升可以感覺到的性能上下功夫。
3.衡量性能
-使用用戶真實環境測試
-在開發中,profile你的代碼
-使用自動的profiling/性能測試
-保持功能執行的歷史數據
-在產品中考慮保留一些(少量的)profiling代碼
第2部分 高性能的頁面下載
1.Yahoo!的14條性能原則
一個頁面工作於3(有時是重疊的)個階段-下載,渲染,運行。14條原則大部分作用於第1個階段。
2.資源優化
-最小化CSS和Javascript文件。推薦使用YUI Compressor(http://developer.yahoo.com/yui/compressor)壓縮。遠離那些所謂的先進的壓縮方案,如Packer。
-合併CSS和Javascript文件。在發佈的時候合併(http://www.julienlecomte.net/blog/2007/09/16)或在運行的時候合併。
-優化圖片資源。如:PngCrush(http://pmt.sourceforge.net/pngcrush)、PngOptimizer(http://psydk.org/PngOptimizer.php)等。
3.減小非壓縮代碼的大小
-下載和解析HTML、CSS、Javascript代碼的成本是很高的。
-用簡練寫法和寫更少的代碼
-用好Javascript庫
-在考慮將大的Javascript文件拆成小的文件(bundle)時,解析和編譯腳本時要花費大量額外的時間
-按需下載代碼(HTML、CSS、Javascript),如,Lazy Loading
* 參見,http://ajaxpatterns.org/On-Demand_Javascript
* 使用 YUI Loader
* Dojo的package system
* JSAN的Import System
4.優化初始渲染(1):綜合技巧
-Consider rendering the first view on the server
-關閉你的HTML標籤提高解析速度。參見http://msdn2.microsoft.com/en-us/library/ms533020.aspx#Close_Your_Tags
-考慮儘早緩存。
-下載基本的資源,延遲或按需下載其他資源。使用YUI ImageLoader。
5.優化初始渲染(2):不要一直等onload
-大部分DOM操作可以在onload事件觸發前完成
-如果你需要控制你的初始化代碼,可以直接寫在<script>裡,並把它放在靠近</body>的位置
-否則,使用YUI事件組件中的onDOMReady方法
YAHOO.util.Event.onDOMReady(function () {
// Do something here...
// e.g., attach event handlers.
});
6.優化初始渲染(3):在頁面下載後,再下載腳本。
-一個好的網站應該在Javascript失效下功能也應該是完整的
-因此,你可以延遲下載腳本
-這樣做對下載其他資源(樣式表、圖片等)是有好處的
-這樣做使網站下載更快
7.優化初始渲染(4):有條件的預下載
-預下載潛在的資源(Javascript、CSS、圖片等)真的可以增強用戶體驗。
-可是,在什麼時候進行功妙的預下載是關鍵,否則,預下載會影響用戶體驗。
-參見http://www.sitepoint.com/article/web-site-optimization-steps/3
-參見http://search.yahoo.com
第3部分 高性能的Javascript
1.減少符號查尋(1):範圍鏈
-每次訪問變量時都會執行查尋
-變量從當前範圍向上執行查尋
-因此,無論何時都在相同範圍中聲明和使用變量
-完全不要使用with,它會阻止編譯器生成代碼時訪問本地變量的速度(因為首先要遍歷原型鏈,然後是範圍鏈等)
-緩存外部變量到本地變量。
不好的寫法:
var arr = ...;
var globalVar = 0;
(function () {
var i;
for (i = 0; i < arr.length; i++) {
globalVar++;
}
})();
好的寫法:
var arr = ...;
var globalVar = 0;
(function () {
var i, l, localVar;
l = arr.length;
localVar = globalVar;
for (i = 0; i < l; i++) {
localVar++;
}
globalVar = localVar;
})();
2.減少符號查尋(2):原型鏈
-訪問主對象上的成員的速度比訪問原型鏈上的成員的速度快25%
-原型鏈越長查尋越慢
function A () {}
A.prototype.prop1 = ...;
function B () {
this.prop2 = ...;
}
B.prototype = new A();
var b = new B();//(譯者:prop2為b的主對象成員,而prop1是原型鏈上的成員)
3.優化對象實例化
-如果你需要創建很多對象,可以考慮添加成員到原型中,而不添加到單個對象的構造器中。
-這樣會減少內存的消耗
-然而會拖慢查尋查尋對象成員的速度
4.不要使用eval
-傳字符串到eval中,需要編譯和解釋,相當的慢!
-完全不要傳一個字符串到setTimeout和setInterval中。可以使用匿名函數代替。
setTimeout(function () {
// Code to execute on a timeout
}, 50);
-完全不要eval做為方法的構造器。
5.優化字符串連接
-在IE(JScript)中,連接兩個字符串會導致一個新的字符串被重新分配資源,同時兩個原字符串被覆制:
var s = "xxx" + "yyy";
s += "zzz";
-因此在IE中,添加字符串到數組中然後再用Array.join連接比直接用+連接快很多(不要用在簡單的連接中)
-其他Javascript引擎(WebKit、SpiderMonkey)已經對字符串連接做了優化
-使用YUI Compressor!
6.優化正則表達式
-儘量不要用RegExp構造,除非你的正則表達式需要實時創建。
-使用test方法測試一個pattern(exec方法會有小的性能問題)
-使用非捕獲組(?:)
-保持pattern的簡單
7.緩存
-在下面情況下應用緩存是合理的:
* 更低成本的獲取一個值
* 值會被經常讀取
* 值不經常改變
-會增加內存消耗(權衡)
-Memoization:
Module Pattern:
var fn = (function () {
var b = false, v;
return function () {
if (!b) {
v = ...;
b = true;
}
return v;
};
})();
Store value in function object:
function fn () {
if (!fn.b) {
fn.v = ...;
fn.b = true;
}
return fn.v;
}
Lazy function definition:
var fn = function () {
var v = ...;
return (fn = function () {
return v;
})();
};
8.如何控制長時間運行處理的Javascript
-在Javascrit的長時間運行處理過程中,整個瀏覽器會被凍結
-因此為了維持好的用戶體驗,確保Javascript一個線程在約300兆秒內完成
-你可以通過用setTimeout將長運行處理拆成的更小處理單元串起來執行
-更多見http://www.julienlecomte.net/blog/2007/10/28/
-例子http://www.julienlecomte.net/blogfiles/javascript/long-running-js-process.html
function doSomething (callbackFn) {
// Initialize a few things here...
(function () {
// Do a little bit of work here...
if (termination condition) {
// We are done
callbackFn();
} else {
// Process next chunk
setTimeout(arguments.callee, 0);
}
})();
}
9.綜合技巧
-簡單的操作符往往比相應的方法要快
c = Math.min(a, b);
c = a < b ? a : b;//更快
myArray.push(value);
myArray[myArray.length] = value;//比上面快
myArray[idx++] = value;//比上面快
-避免使用try...catch在影響性能的部分:
不好的寫法:
var i;
for (i = 0; i < 100000; i++) {
try {
...
} catch (e) {
...
}
}
好的寫法:
var i;
try {
for (i = 0; i < 100000; i++) {
...
}
} catch (e) {
...
}
-If possible, avoid for...in in performance-critical sections
-無論何時分支條件都不改變的情況下,分支應該在外面,不要在裡面:
不好的寫法:
function fn () {
if (...) {
...
} else {
...
}
}
好的寫法:
var fn;
if (...) {
fn = function () {...};
} else {
fn = function () {...};
}
第4部分 高性能的動態HTML
1.文檔樹的修改:使用innerHTML
注意事項http://www.julienlecomte.net/blog/2007/12/38
2.文檔樹的修改:使用cloneNode
注意:expando屬性或附加的事件會丟失
3.文檔樹的修改:使用DocumentFragment
-DocumentFragment(DOM Level 1 Core)是一個輕量級的文檔對象
var i, j, el, table, tbody, row, cell, docFragment;
docFragment = document.createDocumentFragment();
el = document.createElement("div");
docFragment.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
for (i = 0; i < 1000; i++) {
...
}
document.body.appendChild(docFragment);
-它僅僅支持常規DOM方法和屬性的子集
-IE實現DocumentFragment不服從W3C規範
4.限制事件柄的個數
-附加事件到上百個元素上的成本很高
-多個事件柄會增加潛在的內存漏洞
-解決方案:使用事件委託機制,一種依靠事件冒泡的機制
5.限制回流(Reflow)
第5部分 高性能的佈局和CSS
綜合技巧
-使用CSS Sprites
-避免使用Javascript佈局
-避免使用IE表達式
-避免使用IE濾鏡(或儘可能少用)
-優化Table佈局
-優化CSS選擇器http://developer.mozilla.org/en/docs/Writing_Efficient_CSS
第6部分 高性能的Ajax
1.綜合技巧
-完全不要使用同步的XMLHttpRequest。參見http://yuiblog.com/blog/2006/04/04/synchronous-v-asynchronous
-編程處理網絡超時
-解決方案:使用YUI Connection Manager
var callback = {
success: function () { /* Do something */ },
failure: function () { /* Do something */ },
timeout: 5000
};
YAHOO.util.Connect.asyncRequest("GET", url, callback);
2.提升可以感覺到的網絡延遲體驗
-如果數據在提交到服務器端之前經過本地校驗,通常請求的成功率達99.9%
-因此,為了優化用戶體驗,我們可以採用下面的Pattern:
* 當請求發出時要更新UI
* Lock the UI/data structures with the finest possible granularity.
* 讓用戶知道發生了什麼事
* 讓用戶知道為什麼UI被鎖定
* 當成功返回結果後要及時解除鎖定
* 要用優雅的方式處理錯誤
3.綜合技巧
-知道並發HTTP/1.1連接的最大數量
-如果後端支持,支持多元的Ajax請求
-Piggyback unsollicited notifications in a response to an Ajax request.
-用JSON代替XML做為數據交換格式
-推送,不要輪詢。使用COMET向瀏覽器發送實時的通知
-考慮使用本地存儲器緩存數據。
* IE的userData
* Flash本地存儲
* DOM:Storage(WHATWG持久存儲API, 已在Firefox2中實現)
* Google Gears
* 其它
第7部分 性能工具
-YSlow? http://developer.yahoo.com/yslow
-Task Manager
-IE Leak Detector a.k.a Drip [ http://www.outofhanwell.com/ieleak/ ]
-Stopwatch profiling
* AjaxView [ http://research.microsoft.com/projects/ajaxview/ ]
* JsLex [ http://rockstarapps.com/pmwiki/pmwiki.php?n=JsLex.JsLex ]
* YUI profiler [ http://developer.yahoo.com/yui/profiler/ ]
-Venkman or Firebug Profiler [ http://www.getfirebug.com/ ]
(原文:http://yuiblog.com/blog/2007/12/20/video-lecomte/)
網誌存檔
-
▼
2009
(113)
-
▼
6月
(38)
- DIV垂直居中對齊
- 在文章游標處插入文字
- 防止長字串破壞畫面布局
- 各種unicode編碼轉換
- 高性能的Ajax應用-Julien Lecomte
- 常用正規表達式
- 防止誤刷新頁面
- css 更有效率的寫法
- 直接用DataRead讀取DataTable
- 繁簡體中文日文韓文的Unicode字元範圍
- Javascript的延遲執行
- 版面(元素)置中,居中布局
- JavaScript 自訂 trim() 函式
- 表情圖案
- WYSIWYG, Rich Text Editor 線上html編輯器插件
- php 設定時區
- Select, Option, Disabled not work in IE6, IE7
- 計算或限制計算字(元)數
- 如何幫 span 設定寬度又不會被強制換行
- [CSS] IE6 模擬 position:fixed 純 CSS 解法
- HTML ASP 停用網頁頁面的快取暫存..
- ASP.NET: App_Code資料夾中使用Session() 和 Application()
- class,function,sub的應用與區別
- setInterval in IE6
- 用 scrollTop 顯示 div 的最下面
- 移除陣列中的特定元素
- 用CSS診斷HTML原始碼
- 自動將文字的URL轉成HTML超連結
- Javascript取得被選中的字串
- JavaScript arrays indexOf function of IE6/7
- [jquery] 修正IE dblclick()之後會全選的bug
- JavaScript統計字串中內某字元或字串出現次數
- 移除陣列中的重複元素
- php 和 asp 對等的語法
- Regular Expression (RegExp) 正規表達式(正則表達式)
- Javascript 字串處理 (String Operations)
- php中高效能清除HTML 標記、空白字符
- JavaScript 中的 "foreach" 語法
-
▼
6月
(38)