任何一個程式員都很清楚地知道,之所以不把自己所使用的代碼作為最終的代碼來交付是有它合理的原因的。寫代碼時最好要儘可能多寫些注釋,通過編排格式在最大程度上提高代碼的可閱讀性,同時避免過分的簡潔不讓晦澀的代碼給日後的維護帶來困難。之後,我們再使用編譯器等把原始碼轉化成其他格式,一方面達到最優執行,另一方面可以防止反編譯,以免造成原始碼被剽竊。上述的這種模式其實也適用於網站的開發。具體做法是:先製作好網站和網頁的原始碼,再利用一些簡單的技術(比如:減少空白地區,進行圖片和指令碼的最佳化,檔案重新命名等)把原始碼減肥然後你就可以將準備好的網站和網頁交付使用了。
希望這種概念對於你來說並不突兀,因為起碼你很有可能正是在您網站的副本上操作,而不是直接在正在啟動並執行網站上作修改更新。如果你不是這樣做的,那麼請馬上停止閱讀本文,趕緊去給你的網站做個副本吧!無論您的網站的內容是靜態手冊還是非常複雜的使用內容管理系統來驅動(CMS-driven)的應用,這都是唯一正確的開發網站的方式。你要是現在還不相信的話,那麼我敢說很快的等到你損毀了網站的一些檔案卻發現難以恢複的時候你就信了。
在建造網站時,您可能會把注意力放在導致下載速度降低的最大元兇—圖片、二進位檔案(如Flash等)上。減少GIF圖片檔案的顏色數、壓縮JPEG圖片檔案的大小、最佳化SWF檔案固然頗有裨益,其他大有協助的方法也不能小覷。要記得網站效能法則中的第一條,我們得不斷的努力以儘可能少地傳輸資料,不論它是markup檔案、圖片還是指令碼。把精力放在減少(X)HTML、CSS和Javascrīpt檔案的位元組數上似乎是瞎忙乎,可是,這可能恰恰就是最應該注意的地方。
在一個典型的網頁載入過程中,(X)HTML檔案是最先被瀏覽器讀到的。既然這個檔案決定了其他檔案的關係,我們可以管這個檔案叫主檔案(host document)。瀏覽器一旦接收到這個主檔案,便開始解析各種markup;一般在解析的同時,也會觸發一系列對相關對象的請求,例如外部指令碼、關聯的樣式表單、圖片、或嵌入式Flash等等。這些CSS和Javascrīpt檔案有可能繼續觸發一些對相關圖片或指令碼等的請求。這些對相關檔案的請求排成隊列的速度越快,它們到達瀏覽器的速度也就越快,從而越早的開始顯示出頁面來。瞭解了主檔案的重要性,我們便知道把它儘快地傳給瀏覽器並加以解析的重要性,因為儘管主檔案本身相對來說整個傳輸量來說只是一小部分,它卻能夠嚴重地阻礙網頁的載入速度。要明白,使用者才不在乎你使用的位元組數的多少,使用者在乎的是時間!
那麼您具體需要怎麼做才能作到最優傳輸的萬全準備呢?一個基本的方法是減少空白地區,精簡CSS和Javascrīpt,變更檔名,以及對要提交的代碼也採用前述相同的策略,使之越簡潔越好(Google 就是一個例子). 這些目前大家都熟知的通用技巧,在很多網站和一些書中比如Andy King的 《Speed up Your Site: Website Optimisation 》都能找到。本文則列出我們認為最有效最佳化markup和代碼的二十大技巧。當然,您可以手動來做部分最佳化,或者使用網頁編輯器及工具來完成一些最佳化,當然還可以開發出您自己的精簡工具。我們要向你介紹一個由Port80軟體公司開發的工具w3compiler. 它幾乎實現了下面將要提到的所有技巧,而且它也反映出在“真實”世界裡代碼最佳化任務的商業價值。接下來,我們來談談這些技巧!
典型的markup要麼是手工編輯出來的,在非常緊湊,注重標準的格式基礎上加入注釋和空白地區(white space)的檔案;要麼是編輯器產生的,非常之肥胖,帶有過分的格式編排及編輯器特有的通常用來控制結構的注釋,甚至還會有不少重複的和沒有用修飾或者代碼。這兩者都不是最優傳輸的情況。下列技巧既安全又容易,是減小檔案尺寸的好方法:
CSS最佳化CSS也有一套成熟而又簡單的最佳化方法。實際上,時下大多數的CSS都較 (X)HTML更容易壓縮。下面所列的技巧除了最後一條都是安全的。最後一條涉及到用戶端的網頁技術,可能會變得比較複雜。
6、除去CSS中的空白地區
相比起(X)HTML來,CSS對於空白地區沒有那麼敏感,所以除去空白地區便可以極大地減少CSS檔案和style樣式表地區的大小。
7、 除去CSS注釋
如同除去markup代碼中的注釋一樣,由於CSS中的注釋對普通的終端使用者來說並沒有什麼實用價值,所以也應該被除去。不過,如果考慮到較低級的瀏覽器,則在CSS中的style標籤中的屏蔽注釋資訊不可以被除去。
8. 使用最短格式來表示顏色值
和HTML一樣,CSS顏色也可以用詞語或十六進位格式表示。注意,在CSS中這樣做的效果會稍微明顯一些。主要是因為CSS中支援3位的十六進位色值,例如對白色可用#fff 來表示。
9、對CSS的規則進行合并、減少或刪除
CSS中的諸如字型大小、字型重量等規則往往可以使用一種單屬性字型的速記注釋方式來表示。使用得當的話,這個技巧可以讓您把如下的規則:
p {font-size: 36pt;
font-family: Arial;
line-height: 48pt;
font-weight: bold;}
改寫成下面簡短的形式:
p{font:bold 36pt/48pt Arial;}
如果繼承方法使用得當的話,您還會發現在樣式表單中的一些規則可以顯著的減少或乾脆刪掉。到目前為止尚沒有能自動移除規則的工具,所以只能通過手工調整CSS嚮導(Wizard)來進行這些工作。不過即將推出的w2compiler 2.0會有這個功能。
10、對類和ID值進行重新命名
在CSS最佳化中最危險的動作可能是重新命名類或ID值了。看看如下規則:
.superSpecial {color: red; font-size: 36pt;}
可將其更名為sS。而對ID值一樣可以遵循這樣的原則,例如對於:
#firstParagraph {background-color: yellow;}
則可將原來的 ”#firstParagraph” 重新命名為 ”#fp”,並在整個文檔中重複這一動作 。誠然,這樣做可能會涉及到“標識-樣式-指令碼”互相依賴的問題:如果一個“tag”有一個ID值,而這個值又可能不但用於樣式表,還可能用於指令碼參考,甚至可能是一個連結目標地址。在這種情況下,您一旦修改了這個值,您就必須得保證對所有相關的指令碼和連結參考都進行了相應的修改,包括其他檔案中的這個值,所以千萬要小心細緻。
改變類的值相對改變ID值來說,危險性小一些。因為經驗告訴我們,比較起ID值來說,大多數Javascrīpt程式員都不太經常處理類的值。然而,改變類的名稱來縮減CSS的尺寸也面臨著和改變ID名稱同樣的問題,所以再次強調,要小心謹慎。
請注意:最好不要更改名稱屬性,尤其是表單區域中的名稱屬性。因為這些數值也會被伺服器端程式所操作。雖然不是不可能,但對多數的網站來講,要計算好這些相互依賴關係是困難的。
Javascrīpt最佳化越來越多的網站都依賴於Javascrīpt來產生導覽功能表、表格確認和其他各種各樣實用的東西。不足為奇,大多數這些代碼都非常笨重,亟待最佳化。對Javascrīpt代碼的很多最佳化技術同那些用於markup代碼和CSS的技術很相似。不過,對Javascrīpt的最佳化必須更加小心翼翼,因為一旦操作有誤,其後果可能不僅僅是顯示變形,並且可能導致網頁殘缺不全。下面我們先來看看一些最簡單明了的方法,然後再探討那些需要小心操作的技巧。
11. 除去Javascrīpt注釋
除了 注釋,其他所有的 // or /* */ 注釋都可以安全刪除,因為 它們對於最終使用者來說沒有任何意義(除非有人想瞭解您的指令碼是如何工作的)。
12.除去Javascrīpt中的空白地區
有意思的是,除去Javascrīpt中的空白地區並不象想象的那麼有用。一方面,像如下代碼:
x = x + 1;
顯然可以簡短得寫成
x=x+1;
然而,很多隨便的Javascrīpt程式員會忘記在兩行之間加上分號,這時空白地區的除去就會帶來問題。比如,下面合法的Javascrīpt使用了暗示的(implied)分號:
x=x+1
y=y+1
草率地刪除了空白地區則會產生如下運算式:
x=x+1y=y+1
顯然,錯誤就產生了。但如果您加上必需的分號,如下:
x=x+1;y=y+1;
則在位元組數上並沒有減少。然而在此,我們仍然鼓勵這種格式的變化,因為對w3compiler Beta版的測試反饋中,很多人對‘看起來壓縮了的’指令碼非常滿意(也許這是因為視覺上確認了對原始代碼的格式轉變)。他們也喜歡這種處理方法產生的另一個效果,那就是讓交付的代碼變得更難讀。
13.進行代碼最佳化
簡單的方法如除去暗示的(implied)分號,某些情形下的變數聲明或者空斷行符號語句都可以進一步減少指令碼代碼。一些簡略的表達方式也會產生很好的最佳化,例如:
x=x+1;
可以寫成:
x++;
不過得小心謹慎,不然代碼很容易出錯。
14.重新命名使用者自訂的變數和函數
為了閱讀方便,我們都知道在指令碼中應該使用象sumTotal這樣的變數而不是s。不過,考慮到下載的速度,sumTotal這個變數就顯得冗長了。這個長度對於最終使用者來說沒有意義,但對瀏覽器下載則是個負擔。這個時候s就成為較好的選擇了。先寫好方便閱讀的代碼,然後再使用一些工具來處理以供交付。這種處理方式在這裡再一次展示了其價值所在。將所有的名稱都重新用一個或兩個字母來命名將帶來顯著的改善。
15.改寫內建(built-in)對象
長長使用者變數名會造成Javascrīpt代碼過長,除此之外,內建(built-in)對象(比如Window、Document、Navigator等)也是原因之一。例如:
alert(window.navigator.appName);
alert(window.navigator.appVersion);
alert(window.navigator.userAgent);
可以改寫成如下簡短的代碼:
w=window;n=w.navigator;a=alert;
a(n.appName);
a(n.appVersion);
a(n.userAgent);
如果這幾個對象使用頻繁的話,這樣改寫帶來的好處就不言而喻了。事實上這些對象也的確經常被調用。然而我要提醒的是,如果Window或Navigator對象僅僅被使用了一次的話,這樣的替換反而使代碼變得更長。所以手工進行這種最佳化時要格外小心,不過好在目前市面的常用的Javascrīpt代碼最佳化工具都已經考慮到這個因素了。
這個技巧帶來一個對象更名後指令碼執行效率的問題:除了代碼長短上帶來的好處,這種改寫更名實際上還會稍微的提高一點指令碼執行的速度,因為這些對象將會被放在所有被調用對象中比較靠前的位置。Javascrīpt遊戲開發程式員使用這個技巧已經有多年了,下載和執行速度都會有所提高,並且對本地瀏覽器的記憶體花銷也會降低,可謂一石三鳥。
檔案方面的最佳化最後一類的最佳化技巧與檔案和網站的組織有關。下面談及的一些技巧可能會牽扯到伺服器的調整和網站的重構。
16.重新命名使用者訪問不到的獨立檔案和目錄
一些網站往往包含有諸如SubHeaderAbout.gif或 rollover.js等是使用者無法通過URL來訪問的檔案。它們通常都儲存在一個標準名稱的目錄中,比如/images,因此我們常常會在markup代碼中看到這樣的句子:
<img src="http://images.cnblogs.com/SubHeaderAbout.gif">
或者更糟糕的象
<img src="http://www.cnblogs.com/../images/SubHeaderAbout.gif">
既然這些檔案從來都不會被訪問到,對於最終使用者而言,方便不方便閱讀便無關緊要。考慮下載速度的因素,上述句子改成下列形式更有意義:
<img src="/0/a.gif">
然而手工的檔案和目錄的修改工作量太大了,我們可以藉助一些內容管理系統來完成相關的工作,比如將內容重新命名成簡短格式等。前面提到的w3compiler就有自動複製並且檢查相互依賴關係的功能。如果使用得當,這個技巧會給引用這些檔案的(X)HTML檔案減肥不少,並且也讓那些剽竊(X)HTML的人重新使用這些檔案設定了重重障礙。
17.使用URL rewriter來縮短所有的網頁URL
注意在剛才提到的技巧中並不建議對網頁的檔案名稱(例如 products.html)進行重新命名。那樣的話,則下面的標示:
<a href="products.html">Products</a>
就會變成
<a href="p.html">Products</a>
這背後的主要原因是讀者會看到一個這樣的URL: http://www.sitename.com/p.html相比起http://www.sitename.com/products.html來,後者比前者要來的更有意義、更好用的多。
不過,在不犧牲網頁URL原義的前提下,假如我們結合更名技巧和修改伺服器配置的話,我們還是有可能從縮短檔案名稱中得到收穫。譬如,在原始碼中把products.html用p.htmll替換掉,之後再設立一個URL複寫(rewrite)規則,由伺服器端的一個類似複寫模組的過濾器比如 來使用這個規則,從而再把這個URL擴充成一個較為方便使用的值。注意這個竅門,如果這個複寫規則只執行‘外部’(external)重新導向的話,新的URL僅僅會寫在使用者瀏覽器的地址條處,因而會強迫瀏覽器重新請求該頁。在此種情況下,檔案本身沒有被重新命名,僅僅是在原始碼中URL裡使用了重新命名的簡短的檔案名稱。
由於這個技巧依賴於URL的複寫,並且缺少對伺服器端工具(如複寫模組)的廣泛接觸渠道和理解,即使是象w3compiler之類的進階工具在目前也不推崇使用這個技巧。然而, 考慮到像Yahoo!這樣的大型網站通過積極使用該技巧得到了顯著的獲益,這個技巧是不能夠被忽視的,畢竟它給目錄及檔案名稱都是非常具描述性的網站提供了明顯的減肥(X)HTML檔案的效果。
18.除去或縮短副檔名
想想看,其實有些情況下檔案的副檔名並沒有多大用處,比如.gif, .jpg, .js等。瀏覽器不會依賴這些副檔名來顯示頁面,而是在處理時使用MIME類的頭資訊(header)。瞭解了這一點,我們就可以把:
<img src="images/SubHeaderAbout.gif">
簡化為:
<img src="images/SubHeaderAbout">
或是結合檔案名稱目錄名重新命名,我們可以得到:
<img src="/0/sA">.
您可別乍一看這個結果就嚇跑了, .sA.gif仍然是.sA.gif檔案,只不過網頁的訪問者不知道罷了。
不過,為了使用這個相對進階的技巧,您還需要對伺服器來做一下修改。主要要做的工作是啟用一個叫做“內容協商”(content negotiation)的東西。它可能是伺服器內建的,也可能需要一個擴充(比如象Apache的mod_negotation 模組或者IIS裡Port80的PageXchanger )來支援。這樣做會有一個負面的影響,它可能會造成伺服器效能的一點損失。然而,內容協商的功能所帶來的好處遠大於所付出的。乾淨利落的URL可讓您的網站即安全又輕便,甚至還使得自適應的內容傳遞變成可能:根據訪問者瀏覽器的功能和系統的設定來向他傳輸不同類型的圖片或語言!更多的說明請參看同作者所著的 Towards Next Generation URLs 一文。
注意:少了副檔名的URL不會降低您網站在搜尋引擎上的排名。Port80軟體和其他知名網站(如W3C網站)都使用此技術而沒有負面效果。
19. 重構<scrīpt>和<style> 調用方式來最佳化請求次數
我們常常在一個HTML檔案頭中看到這樣標記代碼:
<scrīpt src="/scrīpts/rollovers.js"></scrīpt>
<scrīpt src="/scrīpts/validation.js"></scrīpt>
<scrīpt src="/scrīpts/tracking.js"></scrīpt>
大多數情況下,上述代碼應該被簡化成:
<scrīpt src="/0/g.js"></scrīpt>
其中g.js包含了所有供全域使用的函數。雖然把指令檔分成三份對於維護來說是有道理的,但對於代碼的傳輸則沒有意義。單個的指令碼下載要比三個分離的請求高效的多,並且這也同時簡化了markup代碼的長度。有趣的是,這個方法模仿了傳統程式設計語言編譯器的串連概念
20.考慮代碼級的cache能力
提高網站效能中最重要的方法之一是提高緩衝能力(cacheability)。網頁開發人員對使用<meta> 標籤來設定緩衝控制都很熟悉,可是撇開meta對代理的緩衝毫無用處不說,緩衝能力的真正價值是其對相關對象(比片或指令碼)方面的應用。為了提高緩衝能力,您要考慮根據改變頻率對相關對象進行分段,把更適合緩衝處理的東西放在某個目錄中(比如:/cache或者/images/cache。一旦您按照這個方法來組織您的網站,添加緩衝控制規則就很容易了,這樣你的網站就會向經常來的訪問者“跳”出來。