Pull to refresh

Практический опыт создания Dojo виджетов. Оптимизация производительности Javascript кода

Reading time 6 min
Views 3.2K
Доброго времени суток, хабрасообщество.

Хочу поделиться с вами некоторой полезной, на мой взгляд, информацией, которой будет интересна тем, кто разрабатывает или планирует начать разрабатывать свои Dojo виджеты. Хочу сразу предупредить, что в данной статье я не буду рассказывать как поэтапно создать свой виджет Dojo (однако, если сообществу будет интересна и эта тема, я надеюсь изложить ее в отдельной статье). Вместо этого я хочу остановиться на основных моментах и принципах, которые следует знать и учитывать каждому, кто занимается разработкой Dojo виджетов или имеет какое-либо отношение к этой теме.

image

image


Dojo виджеты


Думаю не будет лишним сказать пару слов о концепции виджетов.
Цель виджетов Dojo — инкапсуляция визуальных Web-компонентов с целью многократного последующего использования. Виджет Dojo обрабатывается на стороне Web-браузера.
Структура виджетов Dojo не зависит от структуры объектов DOM. Каждый виджет Dojo имеет уникальный widgetId и может не содержать ни одного, или же содержать один или более элементов DOM, а также дочерние виджеты Dojo.

Виджет состоит из нескольких файлов. Необходимым является файл JavaScript-кода, в то время как другие необязательны:
  • Файл JavaScript-кода (*.js) содержит логику виджета на JavaScript. Он управляет визуальными элементами с помощью API объектов DOM JavaScript. (В Dojo имеется множество полезных библиотек для упрощения стандартных функций.)
  • HTML-шаблон (*.html) обеспечивает базовое представление виджета в HTML. Если шаблон очень прост, можно представить его виде строки в файле кода.
  • Файл стиля CSS (*.css) содержит визуальные стили, используемые HTML-шаблоном и/или кодом JavaScript.
  • Файлы изображений (*.gif, *.jpg, etc.) содержат изображения, используемые виджетом.

Практический опыт по созданию виджетов.


Программная и декларативная модели создания виджетов Dojo

Dojo позволяет нам создавать виджеты двумя способами: декларативно и программно.
Программно мы можем инстанциировать виджет посредством кода JavaScript:
  1.   var myWidget = new WidgetClass({
  2.     //properties
  3.     },”targetNode”);
* This source code was highlighted with Source Code Highlighter.

Декларативно виджеты создаются непосредственно через разметку:
  1.   <div dojoType=“WidgetClass></div>
* This source code was highlighted with Source Code Highlighter.

Виджеты, объявленные декларативно, будут обнаружены и инстанциированы парсером dojo сразу после body.load события и перед вызовом функций из dojo.addOnLoad. Поэтому, чтобы не блокировать поток исполнения, лучше всего откладывать исполнение ресурсоемких задач на addOnLoad везде где это возможно.
  1. <div dojoType=“myWidgetClasspostCreate=“slowFunction></div>
  2. //Медленный вариант:
  3. slowFunction(){doSlowStuff();}
  4. //Оптимизированный вариант:
  5. slowFunction(){dojo.addOnLoad(doSlowStuff());}
* This source code was highlighted with Source Code Highlighter.

Разработчики Dojo явно тяготеют к описанию интерфейса при помощи специальных атрибутов HTML-тегов, а не напрямую в JS-коде. В ранних версиях библиотеки была доступа именно декларативная модель, когда в HTML-коде разработчик при помощи атрибутов описывал форму, а после загрузки в браузере движок Dojo заменял описания на отрендеренные элементы. Позже, после кардинальной смены архитектуры и перехода на ветку 0.9, а затем и в 1.х оказалось, что программная модель привычнее и, что важнее всего, быстрее, особенно в условиях сложных форм. Да и отладка кажется более простой, а возможности шире.

Widget Startup

Заключительным методом создания виджета является метод startup(). Этот метод особенно полезен в тех случаях, когда нам необходимо выполнить какие-либо действия после того, как виджет полностью был инициализирован и отрендерен, но до того, как он будет отображен на странице. Например, если нам необходимо добавить какой-либо элемент к виджету либо новый tab к tab container-у виджета, то мы можем легко это сделать в методе startup.
Метод startup автоматически будет вызван парсером в случе декларативного объявления виджета, однако если мы создаем виджет програмным способом, то нам необходимо вызывать этот метод вручную.

Отложенное выполнение «тяжелых» функций.

Как мы все прекрасно знаем, о многопоточности в JavaScript не может быть и речи. Весь JavaScript код будет выполняться в одном и том же потоке. Поэтому, выполнение «тяжелых» (ресурсоемких) задач лучше откладывать на последний момент.
Для этого мы можем использовать таймеры в JavaScript, а именно функции setTimeout и setInterval, которые позволяют организовать отложенное выполнение кода через указанный промежуток времени. При этом выполнение отложенного кода смещается в очереди исполнения JS движка, что дает возможность закончить выполнение более критических задач.
  1. dojo.addOnLoad(function(){
  2.   setTimeout(function(){
  3.     //отложенный код
  4. }, 100);
  5. });
* This source code was highlighted with Source Code Highlighter.

Более подробно об использовании таймеров для оптимизации JavaScript кода можно прочесть здесь.

dojo.query

Используйте dojo.query для доступа к DOM. Да, dojo.query гораздо быстрее и имеет более лаконичный синтаксис, чем обычные DOM APIs. Например, этот код:
  1.   // list every node with the class "progressIndicator":
  2.   var list = [];
  3.   var nodes = .getElementsByTagName("*");
  4.   // iterate over every node in the document....SLOOOW
  5.   for(var x = 0; x < nodes.length; x++){
  6.     if(nodes[x].className == "progressIndicator"){
  7.       list.push(nodes[x]); } }
  8.   console.dir(list);
* This source code was highlighted with Source Code Highlighter.

с использованием dojo.query выглядит следующим образом:
  1.   console.dir( dojo.query(".progressIndicator") );
* This source code was highlighted with Source Code Highlighter.

Больше разнообразных примеров использования dojo.query с применением различных запросов вы можете найти тут.

dojo.behavior

Используйте dojo.behavior для добавления функционала. dojo.behavior представляет собой очень простой и легкий механизм «добавления» кода в существующие документы, который основан на dojo.query для отбора DOM-элементов и двух простых команд API:
dojo.behavior.add(), которая добавляет «поведенческий объект» (behavior object) к документу, и dojo.behavior.apply(), который применяет добавленное «поведение».
С примерами использования можно ознакомиться тут.

Делегирование событий

«Навешивание» одинаковых обработчиков на несколько разных элементов может быть оптимизировано при помощи делегирования. Смысл данной оптимизации обработки событий состоит в том, чтобы «повесить» один обработчик на один общий родительский элемент и использовать получаемый в аргументах обработчика event object для доступа к инициатору события.
  1. <div id="container">
  2.   <div id="1">1</div>
  3.   <div id="2">2</div>
  4.   <div id="3">3</div>
  5.   <div id="4">4</div>
  6.   <div id="5">5</div>
  7. </div>
* This source code was highlighted with Source Code Highlighter.

Без делегирования:
  1.   for (var i = 1; i < 6; i++) {
  2.     var el = dojo.byId("" + i);
  3.     dojo.connect(el, "onclick", function() {
  4.       alert(this.id);
  5.    }); }
* This source code was highlighted with Source Code Highlighter.

С использованием делегирования:
  1.   dojo.connect(dojo.byId("container"), "onclick", function(evt) {
  2.     var el = evt.target;
  3.     alert(el.id);
  4.   });
* This source code was highlighted with Source Code Highlighter.


На заметку

И напоследок, общие идеи оптимизации кода с использованием Dojo фреймворка:
  • dojo.parse работает быстрее, чем непосредственный обход DOM;
  • добавление элементов к DOM пагубно влияет на производительность;
  • каждый виджет – это дополнительная нагрузка, поэтому объединяйте их, где это возможно;
  • организовывайте отложенное исполнение везде где это возможно;
  • базовые функции Dojo оптимизированы для производительности, однако виджеты могут быть медленными и ресурсоемкими, если не уделять нужного внимания всем деталям при реализации;

Кроме того, следует помнить и учитывать следующие критические факторы:
  • Скрипты в body замедляют парсинг body;
  • Подгрузка ресурсов блокирует body load event;
  • Обработка массивных конструкций виджетов, подлежащих парсингу, блокирует addOnLoad обработчики;
  • Массивные (медленные) addOnLoad обработчики блокируют последовательное выполнение остальных обработчиков.

Заключение


Ну вот пожалуй и все, на чем я хотел остановиться в данной статье. Конечно данная статья не претендует на полный или «самый лучший» справочник по оптимизации JS кода и/или Dojo виджетов, однако я постарался остановиться на наиболее значимых и часто используемых принципах. Надеюсь эта статья будет полезна всем, кто пользуется или планирует начать пользоваться JavaScript фреймворком Dojo.

upd: Спасибо за карму — перенес в блог Javascript.
Tags:
Hubs:
+5
Comments 5
Comments Comments 5

Articles