1. Отказываемся от UpdatePanel
Одним из самых главных факторов, тормозящих работу вэб-сайта на ASP.NET WebForms – использование контрола UpdatePanel. Для его работы требуется разместить на странице ScriptManager. В этом и заключается первая проблема.
Попробуем создать aspx-страничку и поместим простой Label внутри UpatePanel
<asp:ScriptManager runat="server" /> <asp:UpdatePanel ID="Updatepanel1" runat="server"> <ContentTemplate> <asp:Label runat="server" Text="Hello world!" /> </ContentTemplate> </asp:UpdatePanel>
Запустим проект, посмотрим, во что это превратилось:
<script src="/WebSite1/WebResource.axd?d=ddsVPpuyrEEfoBbqjFYV9oHZ-YB8armGl03nreWb8sxbdd0MXlSne0kVoo7mheRQ1cxLip1L_44SDmzKsEIHZW930AWZ2Zs_ae9a9NTgNck1&t=634790730663322540" type="text/javascript"></script>
<script src="/WebSite1/ScriptResource.axd?d=x2K70A_qh5LLRPvqydlLAwONxKroPWgAGdmlhYHXFoXfUrRwcjMDwh9AgTRQkLVd0gEj8C6MhbyA_hq2RLgNpJxsoak2SQ5Dsi8RIcHR-k72-HxC0Vc2GfaaM_NqOWGS6pN4O31eNf9cYeLVlOWAro2fu6lKP46_8vn-OGH5mmN_8TmV6BQKdue5UaNBp45o0&t=ffffffff940d030f" type="text/javascript"></script> <script type="text/javascript"> //<![CDATA[ if (typeof(Sys) === 'undefined') throw new Error('ASP.NET Ajax client-side framework failed to load.'); //]]> </script>
<script src="/WebSite1/ScriptResource.axd?d=JmrJ_HQ4TGD_jchBEWNRb8OenR4k6OQ7VRyH_toBPQT3JUiqiQs3R0jW7v7zXJ2kEQZHsBtgkthfErRPRvwOKI-uadU-pRHAfl5iwxP1hhqLZX5DmrmatAe9-DtrY8UpvLZcFvWHClUe3sQQzRVLcMCbnpjYQ_AnnrUMVfpTPXHnstGsM4ZnlODzOKmhM5LU0&t=ffffffff940d030f" type="text/javascript"></script> <script type="text/javascript"> //<![CDATA[ Sys.WebForms.PageRequestManager._initialize('ctl02', 'form1', ['tUpdatepanel1','Updatepanel1'], [], [], 90, ''); //]]> </script>
<div id="Updatepanel1"> <span>Hello world!</span> </div>
Видим, что для вывода простого текста внутри UpdatePanel потребовалось 2 кб html и еще почти 100 кб скриптов. Тоже самое без UpdatePanel занимает примерно 500 байт.
Вторая же проблема – жизненный цикл страницы. То, что полностью отсутствует в ASP.NET MVC, и то с чем приходится уживаться в ASP.NET WebForms. Подробнее отличия есть здесь.
При любом событии внутри UpdatePanel происходит PostBack и выполняются все события страницы, в которых могут происходить трудные вычисления или запросы к базе данных. Если не использовать кругом конструкцию вроде:
if(!Page.IsPostBack) { Do something… }
то приложение будет работать не так быстро, как хотелось бы.
Простой пример:
Пользователь вводит номер заказа и нужно вывести его текущий статус, без перезагрузки страницы целиком.
Как это можно сделать, не используя UpdatePanel.
Создаем класс обработчик http-запросов
public class CheckOrder : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "application/json"; Order order = OrderService.GetOrder(context["number"]); if(order != null) { var statusResult = new { Status = order.Status, Comment = order.Comment }; context.Response.Write(JsonConvert.SerializeObject( statusResult)); } } public bool IsReusable { get { return true;} } }
Тут еще пригодится библиотека Newtonsoft.Json для сериализации объектов в JSON. Но можно обойтись и без нее возвращая просто текст.
Далее создаем js функцию, которая при помощи jquery при нажатии на кнопку «Проверить» будет отправлять через ajax get запрос на получение статуса.
function CheckOrder(ordernum) { $.ajax({ async: false, dataType: "json", cache: false, url: "checkorder.ashx", data: { number: ordernum }, success: function (status) { $("#orderStatus").text(status.Status); $("#orderComment").text(status.Comment); }, error: function () { $("#orderStatus").text("Ошибка получения статуса")); } }); }
Все очень просто, но эффективно. Также вместо httphandler можно обойтись статическим методом в классе страницы. Для этого достаточно пометить его атрибутом [WebMethod].
2. Избавляемся от ViewState
ViewState – еще одна особенность WebForms. У нее есть свои плюсы и минусы, которые хорошо описаны в этой статье. Однако в большинстве случаев без него можно обойтись. В старых версиях AdvantShop.Net ViewState на разных страницах был от 15 до 30 кб, что было очень неприятным, поскольку эти килобайты пересылались на каждом обращении к страничке. Как можно этого если не избежать, то хотя бы минимизировать риски?
Достаточно всего лишь прописать на Мастер-Странице
<%@ Master Language="C#" CodeFile="MasterPage.master.cs" Inherits="MasterPage" EnableViewState="false" ViewStateMode="Disabled" %>
Однако начнутся проблемы с такими контролами, которым необходим ViewState для хранения своего состояния – например, DropDownList или ListView. В таких случаях придется ViewState все же включить, но его можно будет отключить для каждого контрола, который его не использует. Ссылка для заинтересовавшихся.
3. Уходим от стандартных контролов и AjaxControlToolkit
Так сложилось, что в Microsoft при разработке контролов для ASP.NET не особо задумывались о чистоте и оптимальности верстки, количестве запросов и скорости работы этих самых контролов. GridView — очень медленный, TreeView генерирует ужасную верстку, Calendar труден в настройке и захламляет html. Те, кто ими пользовались, могли сами в этом убедиться.
Простой выход использовать jquery плагины или любые другие js фреймворки.
4. Минимизируем контент страниц
Чтобы повысить скорость работы сайта необходимо уменьшить количество http запросов к серверу и максимально сжать статический контент страниц: изображения, css и js файлы. С изображениями тут все понятно – используем выше степень сжатия и спрайты. Css и js файлы можно сжать с помощью специальных минимизаторов. Однако это неудобно, приходится хранить две версии: полную — для редактирования и дебага, и минимизированную — для продакшена.
Другой способ – использовать библиотеку SquishIt. Как это делать, можно почитать тут. В результате комбинируем и минимизируем все js и css в два файла, уменьшаем количество запросов и увеличиваем время загрузки страницы примерно на две секунды.
До применения:
После:
5. Сжимаем HTML
Большинство браузеров поддерживает сжатие контента GZip либо Deflate. Создаем класс, который будет выполнять сжатие.
namespace AdvantShop.Core.Compress { public class CompressContent : IHttpModule { public void Dispose() { // Nothing to dispose; } public void Init(HttpApplication context) { context.PreRequestHandlerExecute += PreRequestHandlerExecute; } private static void PreRequestHandlerExecute(object sender, EventArgs e) { var app = (HttpApplication)sender; HttpRequest request = app.Context.Request; HttpResponse response = app.Context.Response; if (request.FilePath.Contains(".aspx") || request.FilePath.Contains(".js") || request.FilePath.Contains(".css")) { if (!(request.Browser.IsBrowser("IE") && request.Browser.MajorVersion <= 6)) // IE6 does not support compression { string acceptEncoding = request.Headers[HttpConstants.HttpAcceptEncoding]; if (!string.IsNullOrEmpty(acceptEncoding)) { acceptEncoding = acceptEncoding.ToLower(CultureInfo.InvariantCulture); if (acceptEncoding.Contains(HttpConstants.HttpContentEncodingGzip)) { response.Filter = new HttpCompressStream(response.Filter, CompressionMode.Compress, HttpCompressStream.CompressionType.GZip); response.AddHeader(HttpConstants.HttpContentEncoding, HttpConstants.HttpContentEncodingGzip); } else if (acceptEncoding.Contains(HttpConstants.HttpContentEncodingDeflate)) { response.Filter = new HttpCompressStream(response.Filter, CompressionMode.Compress, HttpCompressStream.CompressionType.Deflate); response.AddHeader(HttpConstants.HttpContentEncoding, HttpConstants.HttpContentEncodingDeflate); } } } else { response.Filter = new HttpCompressStream(response.Filter, CompressionMode.Compress, HttpCompressStream.CompressionType.None); } } } } }
Затем, чтобы подключить этот модуль в свое приложение просто добавим в web.config строчки:
<modules> <add name="CompressContent" type="AdvantShop.Core.Compress.CompressContent"/> </modules>
Получаем очень хороший результат – сжатие текста в четыре раза. Причем сжимается не только html но также js и css.
До:
После:
6. Кешируем UserControls
Чтобы закешировать User Control, достаточно поместить в заголовок контрола строку вида:
<%@ OutputCache Duration="60" VaryByParam="CategoryID" %>
Таким образом, мы указываем, что контрол будет храниться в кеше 60 секунд и создастся своя версия кеша в зависимости от параметра из Request[“CategoryID”].
Вместо заключения
Это только основные методы ускорения, которые в большей степени применимы к WebForms. Однако не стоит забывать и про другие методы, особенно те, на которые указывает эта полезная тулза — PageSpeed.
ссылка на оригинал статьи http://habrahabr.ru/company/advantshop/blog/155985/
Добавить комментарий