優化網站設計(一):減少請求數


前言

網站設計的優化是一個很大的話題,有一些通用的原則,也有針對不同開發平台的一些建議。這方面的研究一直沒有停止過,我在不同的場合也分享過這樣的話題。

作為通用的原則,雅虎的工程師團隊曾經給出過35個最佳實踐。這個列表請參考

Best Practices for Speeding Up Your Web Site  http://developer.yahoo.com/performance/rules.html 

同時,他們還發布了一個相應的測試工具Yslow http://developer.yahoo.com/yslow/

我強烈推薦所有的網站開發人員都應該學習這些最佳實踐,並結合自己的實際項目情況進行應用。

接下來的一段時間,我將結合ASP.NET這個開發平台,針對這些原則,通過一個系列文章的形式,做些講解和演繹,以幫助大家更好地理解這些原則,並且更好地使用他們。

 

准備工作

為了跟隨我進行后續的學習,你需要准備如下的開發環境和工具

  1. Google Chrome 或者firefox ,並且安裝 Yslow這個擴展組件.請注意,這個組件是雅虎提供的,但目前沒有針對IE的版本。
    1. https://chrome.google.com/webstore/detail/yslow/ninejjcohidippngpapiilnmkgllmakh
    2. https://addons.mozilla.org/en-US/firefox/addon/yslow/
    3. 你應該對這些瀏覽器的開發人員工具有所了解,你可以通過按下F12鍵調出這個工具。
  2. Visaul Studio 2010 SP1 或更高版本,推薦使用Visual Studio 2012
    1. http://www.microsoft.com/visualstudio/eng/downloads 
  3. 你需要對ASP.NET的開發基本流程和核心技術有相當的了解,本系列文章很難對基礎知識做普及。

 

本文要討論的話題

這一篇文章討論的是第一個原則:應該盡可能加減少請求數。這個原則的說明請參考  http://developer.yahoo.com/performance/rules.html#num_http

我們的網頁在加載的時候,為了提供更加豐富的內容和效果,除了頁面本身這個請求之外,總是需要加載其他一些資源的,例如我們常見的Javascript文件,css文件,圖片,甚至還會有一些Flash組件等等。這本無可厚非,但如果過多的外部請求,會很直接地降低頁面加載的速度。

我們來看一個例子吧。例如我們經常訪問的博客園的首頁

image

這個網頁的加載需要多少次請求呢?(如果不考慮緩存的話)

image

我們看到,請求數為55個。我們進一步通過Yslow來分析,可以得到綜合的報表

imageimageimage

應該說博客園的設計已經比較注意很多細節了。他們得到了B級的評分。我們再來看看其他一些主要的門戶的表現吧(從左至右,依次是新浪,搜狐,騰訊,淘寶),他們都只得到D級的評分。

【備注】這些評分只是作為一個參考,不做任何的結論和推論。

imageimageimageimage

 

如何減少請求數?

我們可以通過如下的幾個方法來減少請求數:

  1. 合並外部資源文件(如javascript,css,圖片文件)
    1. 圖片的合並,是將多個圖片合並為一個圖片,然后采用css的一些設置(background-image,background-position) 來使用它們。這個很簡單實用(但是效果也是顯著的)。本文將不做演示。
    2. javascript和css文件的合並,這個可能大家不太經常注意到。本文的后續部分將對此進行演示。
  2. 使用Inline images 這種方式. 這個方式可能依賴於瀏覽器的實現,目前並不是所有的瀏覽器都支持。所以本文也不做演示。

 

合並javascript文件和css文件

對於這兩種文件的合並而言,我們當然可以手工去做(copy,paste),把一個文件的內容粘貼在另外一個文件內容的底部即可。但這種方式有幾個缺點:

  1. 破壞了原有文件的結構
  2. 不同頁面需要的文件組合可能是不一樣的,這種情況下會需要產生多個不同的文件,而且需要比較小心地維護它們
  3. 如果文件的內容發生變化,就需要重新再來一次

 

所以,我並不是很推薦用這種手工合並的方法,事實上,我們有更好的工具來實現, 並且在ASP.NET的一些框架(例如ASP.NET MVC)里面已經有了內置的實現。

我們先來看一個例子,下面是一個典型的ASP.NET MVC項目

image

我找了其中的一個用戶注冊頁面,在IE中進行查看

image

我們看到默認情況下,完成這個頁面其實要執行8個請求。但經過簡單的處理(添加一行代碼)之后,我們可以看到如下的效果

image

而且如果你細心看的話,在這個頁面中請求的javascript文件似乎看起來經過了特殊的處理(路徑比較特殊)。那么,這是如何實現的呢?

原來,在MVC項目中,默認會有一個所謂的BundleConfig的類,它提供了一個方法RegisterBundles,如下所示

using System.Web;
using System.Web.Optimization;

namespace MvcApplication1
{
    public class BundleConfig
    {
        // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
                        "~/Scripts/jquery-ui-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.unobtrusive*",
                        "~/Scripts/jquery.validate*"));

            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));

            bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
                        "~/Content/themes/base/jquery.ui.core.css",
                        "~/Content/themes/base/jquery.ui.resizable.css",
                        "~/Content/themes/base/jquery.ui.selectable.css",
                        "~/Content/themes/base/jquery.ui.accordion.css",
                        "~/Content/themes/base/jquery.ui.autocomplete.css",
                        "~/Content/themes/base/jquery.ui.button.css",
                        "~/Content/themes/base/jquery.ui.dialog.css",
                        "~/Content/themes/base/jquery.ui.slider.css",
                        "~/Content/themes/base/jquery.ui.tabs.css",
                        "~/Content/themes/base/jquery.ui.datepicker.css",
                        "~/Content/themes/base/jquery.ui.progressbar.css",
                        "~/Content/themes/base/jquery.ui.theme.css"));

        }
    }
}

 

這個方法會在Global.asax文件中調用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace MvcApplication1
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            //BundleTable.EnableOptimizations = false;//啟用這一行,則使用Bundle的機制進行文件打包
            AuthConfig.RegisterAuth();
        }
    }
}

 

在具體的頁面中,如果需要用到上述的腳本組合,則可以使用下面這樣的語法來調用

@Scripts.Render("~/bundles/jqueryval")

 

這就是所有的秘密。

那么,這個技術是不是只能使用在MVC中,在我們另外一種開發框架(ASP.NET Web Forms)中是否也可以使用呢?

答案是:可以的。而且這個技術,確實是最早就是用在ASP.NET Web Forms里面,只不過,因為這方面的文檔較少,所以可能大家用的不多而已。下面是我作為演示用的一個簡單的ASP.NET Web Forms的項目:

image

我們看到,在頁面中,我們添加了三個腳本引用,這樣的話,自然在打開頁面的時候,需要單獨請求這三個腳本文件。

image

我們是否可以將這三個文件合並成一個請求呢?請跟隨我來進行如下的操作

首先,添加一個組件,這是微軟官方發布的System.Web.Optimization,顧名思義,這就是為了優化網絡開發用的

image

按照一般的慣例,我們在項目中添加一個文件,來進行Bundle的注冊

using System.Web.Optimization;

namespace WebApplication1
{
    public class BundleConfig
    {
        public static void RegisterBundle(BundleCollection config)
        {
            config.Add(new ScriptBundle("~/default").Include("~/scripts/jquery-2.0.0.min.js", "~/scripts/knockout-2.2.1.js", "~/default.js"));
        }
    }
}

 

然后,我們修改Global.asax文件,添加如下的代碼

using System;
using System.Web.Optimization;

namespace WebApplication1
{
    public class Global : System.Web.HttpApplication
    {

        protected void Application_Start(object sender, EventArgs e)
        {
            BundleConfig.RegisterBundle(BundleTable.Bundles);
            BundleTable.EnableOptimizations = true;
        }

    }
}

最后,我們在頁面上也做相應的修改,如下所示(請注意粗體部分)

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>
<%@ Import Namespace="System.Web.Optimization" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <%= Scripts.Render("~/default") %>
</head>
<body>
    <form id="form1" runat="server">
        <div>
        </div>
    </form>
</body>
</html>

很不錯,我們現在可以查看一下頁面運行起來的效果

image

很明顯,原先的三個請求,現在變成了一個請求。需要注意的是,如果我們去計算文件大小,這個合並之后的文件,體積會比之前三個文件體積總和略小一些。所以你可以理解為這里存在一定的壓縮,但這個壓縮比是不大的(尤其是原有的javascript文件本身就經過了壓縮的情況下)。關於javascript文件或者css文件的壓縮,后續會有專門的文章介紹。

上面的例子,演示的是javascript文件的合並。其實,css文件的合並也是類似的做法,區別在於要使用StyleBundle : http://msdn.microsoft.com/en-us/library/system.web.optimization.stylebundle.aspx

 

總結

本文介紹了網站優化的第一個原則(盡量減少請求數),我帶領大家分析了為什么需要考慮這個原則,以及具體如何實現(包括在MVC和Web Forms的做法)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM