Pull to refresh

Google Web Toolkit и клиентская оптимизация

Reading time5 min
Views5.2K
Чем медленнее загружается и работает web-приложение, тем меньше пользователей захотят им воспользоваться. Google понимает это как никто другой, поэтому в созданном ими Web Toolkit особое внимание уделено скорости работы получаемых с его помощью web-приложений.

Статья рассказывает о том, какие приемы клиентской оптимизации используются в GWT.

Отдельная версия приложения для каждого браузера


У каждого браузера есть свои особенности, что известным образом усложняет жизнь разработчику. Так, например, чтобы получить объект XMLHttpRequest (необходимый для выполнения асинхронных запросов к серверу из JavaScript) в IE6, проходится использовать ActiveXObject:
var xhr = new window.ActiveXObject("Microsoft.XMLHTTP");

Все остальные (отличные от IE) браузеры предоставляют встроенную поддержку объекта XMLHttpRequest:
var xhr = new window.XMLHttpRequest();

Обычно (так устроено большинство JavaScript-библиотек) в подобных ситуациях в web-приложение включают все браузеро-зависимые реализации, а в каждом конкретном браузере используют только одну из них, выбирая её по ходу выполнения, то есть после того как будут загружены и разобраны в том числе и не нужные реализации.

В Google Web Toolkit применяют отличное (во всех смыслах) решение: для каждого браузера собирается отдельная версия web-приложения, называемая пермутацией. Каждая пермутация содержит всё, что необходимо для работы только в одном браузере, поэтому, например, «огненному лису» никогда не придется загружать и разбирать JavaScript или CSS специфичные для IE.

Оптимизация, минимизация и обфускация


Чтобы ускорить загрузку web-приложения, JavaScript и CSS обычно минимизируют, например, с помощью YUI Compressor, который за счет удаления пробельных символов и прочих необязательных конструкций, а также в результате обфускации, значительно сокращает их размер.

Google Web Toolkit также проводит минимизацию и обфускацию, но на вход минимизатора поступает JavaScript, не написанный человеком, а полученный в результате работы Java-в-JavaScript компилятора. Компилятор безопасно удаляет неиспользуемый код, разворачивает методы, оптимизирует полиморфные отношения, вычисляет константные выражения и делает многое другое, в результате чего получается оптимизированный (по размеру и по скорости работы) JavaScript.

Небольшой (примитивный) пример:
public class CircleMath {
 
  public static double getArea(double radius) {
    return Math.PI * radius * radius;
  }
 
  public static double getCircumference(double radius) {
    return Math.PI * radius * 2;
  }
 
}
 

 
double a = CircleMath.getArea(7.5);
double c = CircleMath.getCircumference(radius);

Во время компиляции CircleMath будет удален, его статические методы будут заменены inline-вставками, а математические выражения оптимизированы. В результате получится такой JavaScript:
var a = 176.714586788, c = 6.283185308 * radius;

Оптимизация для лучшего сжатия Gzip


Все современные браузеры поддерживают сжатие, которое (при правильной настройке web-сервера) позволяет значительно уменьшить размер передаваемых данных. Особенно хорошо сжимаются HTML, CSS и JavaScript, уменьшаясь в среднем на 75%.

Такие во многом зависящие от самих данных результаты показались инженерам Google неудовлетворительными, поэтому они модифицировали обфускатор, входящий в состав Google Web Toolkit так, чтобы получающийся на выходе обфусцированный код всегда сжимался Gzip как можно сильнее.

Чтобы представить, как это работает, сожмем с помощью GNU Gzip две строки:
a b c b a c a b c a b c b a c a b c
a a a a a a b b b b b b c c c c c c

Можно заметить, что обе строки состоят из одинакового числа одинаковых символов, а отличаются только порядком некоторых из них, при этом после сжатия первая строка не уменьшится ни на байт, тогда как вторая станет на 3 байта короче. Аналогичным образом, если поменять порядок объявления функций в JavaScript, так чтобы повторяющийся код, находился в рамках одного "скользящего окна", скрипт будет сжиматься сильнее, чем при случайном порядке объявления функций.

CSS sprites и встроенные изображения (data:URL)


CSS спрайты и встроенные изображения помогают уменьшить число обращений к серверу, необходимых для загрузки интерфейсной графики web-приложения. В большинстве случаев можно было бы ограничиться одними встроенными изображениями, но так как они не поддерживаются некоторыми все ещё широко-используемыми версиями IE, приходится применять обе методики.

Для построения интерфейса пользователя Google Web Toolkit позволяет использовать привычные технологии: HTML и CSS, несколько расширенный синтаксис которых помогает без каких-либо дополнительных усилий и знаний решить проблему обеспечения кросс-браузерной оптимизации загрузки изображений:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder">
 
  <ui:image field="image1" src="1.png"/>
  <ui:image field="image2" src="2.png"/>
 
  <ui:style>
 
    @sprite .image1 {
      gwt-image:        "image1";
      /* ... CSS properties ... */
    }
 
    @sprite .image2 {
      gwt-image:        "image2";
      /* ... CSS properties ... */
    }
 
  </ui:style>
 
  <div>
    <div class="{style.image1}"></div>
    <div class="{style.image2}"></div>
  </div>
 
</ui:UiBinder>

Во время сборки web-приложения, включающего такой UI-шаблон, 1.png и 2.png будут объединены в одно изображение, которое будет использовано в пермутациях для IE6 и IE7 посредством CSS Sprites. Во все остальные пермутации исходные изображения будут встроены в виде data:URL. В обоих случаях все необходимые свойства будут добавлены в CSS-классы image1 и image2 автоматически.

Разделение приложения на модули


Механизм пермутаций Google Web Toolkit, позволяет современным браузерам загрузить HTML, Javascript, CSS и изображения — всё компоненты web-приложения — в виде единого файла за одно обращение к серверу.

С ростом функциональности web-приложения неизбежно растет размер пермутаций, а соответственно увеличивается время необходимое для загрузки каждой из них. Может наступить момент, когда «холодный старт» (кэш браузера пуст), даже с учетом всех возможных оптимизаций, начнет занимать неприемлемо большое время.

На этот случай Google Web Toolkit предоставляет возможность разбить web-приложение на несколько отдельно-загружаемых модулей. Таким образом основные функции большого приложения можно сделать доступными для пользователя сразу после загрузки небольшого стартового модуля, а остальные, обеспечивающие дополнительную функциональность модули подгружать по мере надобности. Модули создаются и подгружаются автоматически, от разработчика требуется лишь указать точки разделения.

Используя модули, разработчики Google Wave смогли довести среднее время загрузки своего детища до нескольких секунд, хотя полный размер этого «монстра» равен примерно 3 Мбайтам.
Tags:
Hubs:
Total votes 33: ↑30 and ↓3+27
Comments78

Articles