The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

加速前端網頁效能的14條規則

Steve Souders 這個傢伙寫了一本書叫做:High Performance Web Sites: Essential Knowledge for Front-End Engineers

這本書裡定義了14條讓你的網頁加速的方法,分別如下:

  1. Make fewer HTTP requests
  2. Use a CDN
  3. Add an Expires header
  4. Gzip components
  5. Put CSS at the top
  6. Move JS to the bottom
  7. Avoid CSS expressions
  8. Make JS and CSS external
  9. Reduce DNS lookups
  10. Minify JS
  11. Avoid redirects
  12. Remove duplicate scripts
  13. Turn off ETags
  14. Make AJAX cacheable and small

而以下是我研��後的心得分享:

1. Make fewer HTTP requests

    - 減少 Image 的 Request 次數

        - 使用 CSS Sprites 技巧
          http://alistapart.com/articles/sprites
       
        - 使用 Image Map 技巧
   
        - 使用 Inline Image 技巧 ( data: )
          http://tools.ietf.org/html/rfc2397
         
          P.S. 可以開發一個 Inline Image 產生器!
         
          P.S. 建議將 Inline Image 快取在 CSS 檔案中,這樣可避免 HTML 太大

    - 減少 CSS / JavaScript 的 Request 次數
     
        - 整合多個分開的 CSS / JavaScript

2. Use a CDN

    - N/A

3. Add an Expires header

    - 加入 Expires Header 到 Image, CSS, JavaScript 檔案裡

4. Gzip components

    - 壓縮 HTML, JavaScript, StyleSheet, XML, JSON,但切記「不要壓縮 Images, PDF 檔案」!

    - 設定方法
   
        Apache 2.x: 使用 mod_deflate
       
            AddOutputFilterByType DEFLATE text/html text/css application/x-javascript

        IIS 6.0
       
            Enabling HTTP Compression (IIS 6.0)
            http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/502ef631-3695-4616-b268-cbe7cf1351ce.mspx?mfr=true
           
            Using HTTP Compression for Faster Downloads (IIS 6.0)
            http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/25d2170b-09c0-45fd-8da4-898cf9a7d568.mspx?mfr=true
       
            Enabling HTTP Compression in IIS 6.0
            http://dotnetjunkies.com/Article/16267D49-4C6E-4063-AB12-853761D31E66.dcik
           
            IIS Compression in IIS6.0
            http://weblogs.asp.net/owscott/archive/2004/01/12/57916.aspx

        IIS 5.0
       
            HOW TO: 啟用 IIS 中的 ASPX 壓縮
            http://support.microsoft.com/kb/322603
           
           
    - HTTP Header Style
   
        HTTP request

            Accept-Encoding: gzip, deflate

        HTTP response

            Content-Encoding: gzip
            Vary: Accept-Encoding            ( 這行是給 Proxy Server 看的 )

    - 其他注意事項
   
        - 個人化的頁面要加上 ==>  Cache-Control: Private
       
        - 移除 ETags (Rule 13)

5. Put CSS at the top

    - 一定要將 CSS 放在 <head> 區段載入!
   
    - 使用 <LINK> 標籤,不要使用 @import 語法

    - Avoid Flash of Unstyled Content (FOUC) in IE
      http://www.bluerobot.com/web/css/fouc.asp/

        <!-- Hack to avoid flash of unstyled content in IE -->
        <script type="text/javascript"> </script>

6. Move JS to the bottom

    - 一定要將所有 JavaScript 都擺在頁面最下方
   
        </body> 之前
        因為所有在 JavaScript Include 以下的 HTML 在 JS 還沒讀完前,都不會顯示畫面
   
    - 把 JavaScript 的 Code 都放在 onload 執行!!

7. Avoid CSS expressions

    - 不要使用 CSS expressions 因為可能這段 expression 會在每一次 mouse move, resize, scroll, key press 時執行!
   
    - 要使用 EventHandler 去執行這些 Expression (JS Code)

8. Make JS and CSS external

    - 反正 JS 跟 CSS 拉到外面成獨立檔案就是好的,但「首頁」可以例外!
   
    - 使用 Post-onload download 技巧

        download external files after onload
        window.onload = downloadComponents;
        function downloadComponents() {
            var elem = document.createElement("script");
            elem.src = "http://.../file1.js";
            document.body.appendChild(elem);
            ...
        }
       
        範例:http://stevesouders.com/hpws/dynamic-inlining.php
   
        作法:
       
            1. 在 Server-side 判斷使用者 Browser 有設定 Cookie["hasPostOnloadDownload"]

                1.1. 若沒有,就使用 post-onload download 動態下載 CSS & JS
               
                1.2. 若有用,就直接用 <script src="xxxx.js"></script> 下載,Browser 會抓取 Cache 的版本

            P.S. cookie expiration date is key
   
9. Reduce DNS lookups

    - 在一個頁面中,不要超過 2 - 4 個 Hostname,不然會降低頁面載入速度
    
    - 開啟 Keep-Alive 支援

10. Minify JS

    - jsmin
      http://crockford.com/javascript/jsmin
     
      下載後更名成 jsmin.zip 解壓縮出 jsmin.exe 即可執行
     
      jsmin.exe < input.js > output.js    (注意:所有 UTF-8 編碼的 js 檔會變成 ANSI as UTF-8 編碼)
   
    - dojo compressor
      http://dojotoolkit.org/docs/shrinksafe

11. Avoid redirects

    - 參考資料:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

    - 避免 Redirect 產生的方式
   
        * 網址若省略檔名時,最後面一定要加上 / 結尾
       
        * 追查 Log 檔
       
            - 查看 Log Referer
   
12. Remove duplicate scripts

    - 這一點雖然很呆,不過連 MSN Space, Yahoo 都有類似的情況!
   
    - 在 ASP.NET 的元件中(UserControls, WebControls),請多使用 Page.ClientScript.RegisterScriptInclude 的方式!

13. Turn off ETags

    - 基本格式
   
        * unique identifier returned in response

            ETag: "c8897e-aee-4165acf0"
            Last-Modified: Thu, 07 Oct 2004 20:54:08 GMT
           
        * used in conditional GET requests
       
            If-None-Match: "c8897e-aee-4165acf0"
            If-Modified-Since: Thu, 07 Oct 2004 20:54:08 GMT

    - if ETag doesn't match, can't send 304

    - ETag format

            Apache:
           
                ETag: inode-size-timestamp
           
            IIS:
           
                ETag: Filetimestamp:ChangeNumber

    - IIS 設定方式
   
        自動設定方式
       
            ETagFix - keep IIS eTags from changing
            http://www.snapfiles.com/get/etagfix.html
           
            原創公司:ISAPILab http://www.isapilabs.com/
           
            安裝 http://www.isapilabs.com/downloads/ETagFix-setup.exe 之後會重新啟動 IIS 之後就沒問題了!
           
            Related: http://www.snapfiles.com/Freeware/server/fwiis.html
           
            Note:
           
                在 IIS 5.0 可以正常運作
               
                在 IIS 6.0 必須要執行在 Isolate Mode 才可以使用 ISAPI,預設是不能用的!
    
        手動設定方式
   
        * 如果不是用 Windows Server 2003 SP1 要先安裝 Hotfix 900245
          http://support.microsoft.com/kb/900245/
     
        * 先安裝 IIS 6.0 Resource Kit
          http://www.microsoft.com/downloads/details.aspx?FamilyId=56FC92EE-A71A-4C73-B628-ADE629C89499&displaylang=en
       
        * 使用 Metabase Explorer 開啟 LM \ W3SVC 新增 DWORD to 2039 其 Value="0" ( 每一台 WebFarm 底下的電腦都要這樣設定 )
       
        * 重新啟動 IIS

              net stop iisadmin /y
              net start w3svc
              net start smtpsvc

        參考資料

            * 您可能會當您使用 Internet Explorer 6, 試著存取 Web 應用程式所裝載在 Internet Information Services 6.0 Web 效能非常低
              http://support.microsoft.com/kb/922703/

    - Apache 設定方式

        FileETag none

14. Make AJAX cacheable and small

    - XHR, JSON, iframe, dynamic scripts 都一樣可以被快取(Cached)、最小化(minified)和壓縮(gzipped)

    - 個人化的頁面回應時,一樣要做快取,但是針對「該使用者」做快取(Cache-Control: private)

        - 在使用 XHR 時,URL 可以加上「最近的修改時間」在 QueryString 裡。
       
            GET /yab/[...]&r=0.5289571053069156 HTTP/1.1
       
        - 回傳資料時的 Header 可以用 Cache-Control: private + Last-Modified,使用者就不會一直連到網站抓網站了!!

        設定 Cache Header 注意事項
       
        * 個人化的頁面一定要設定
       
            Response.Cache.SetCacheability(HttpCacheability.Private);
       
        * 如果要 Cache 頁面或 External Reference 檔案(CSS/JS)一定要加上
       
            Response.Cache.SetLastModified(DateTime.Now);
           
            如果不加上 MaxAge 的話,將會無限時間的 Cache 直到下次 Reload 或開新 Browser 手動輸入網址進入網頁
       
        * 如果要指定 Cache 的時間要加上
           
            Response.Cache.SetMaxAge(new TimeSpan(0, 0, 0, 10));
            Response.Cache.SetExpires(DateTime.Now.AddSeconds(10));
       
        * 如果不要頁面被 Cache 的話
       
            Response.Cache.SetMaxAge(TimeSpan.Zero);
           
            Response.Cache.SetExpires(DateTime.MinValue);