Статьи

Использование Ant для создания библиотеки JavaScript

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


Для этого урока вам понадобится NetBeans с установленным Ant. Я часто использую:

  • NetBeans 7.0.1 для проектов PHP — версия Ant 1.12.1
  • NetBeans 7.1 для проектов JSP — версия Ant 1.14.1

Инструмент Ant в версии PHP является немного ограниченной версией, но идеально подходит для наших целей, потому что проекты PHP не сложны с автоматически генерируемым файлом сборки. Поэтому для этого урока я продемонстрирую версию PHP. Однако Ant, конечно же, доступен в Apache и широко используется в IDE, таких как Eclipse. Для сообщества .Net C # есть инструмент под названием Nant , который я использую в своих проектах .NET — он очень похож.


В моей первой серьезной попытке создать одностраничное Ajax-приложение я получил список из почти 40 тегов сценариев, время запуска которых составляло более минуты. Чтобы сделать проект управляемым, мне нужно было содержать код в нескольких модулях, не говоря уже о всех необходимых модулях YUI. Прочитав блоги, написанные командой YUI, я понял, насколько важно для производительности сократить количество тегов сценариев до как можно меньшего числа. Отсюда мой интерес к объединению и минимизации файлов JavaScript.

Объединение нескольких файлов уменьшает дополнительные байты из заголовков HTTP, а также потенциальную задержку передачи, вызванную медленным запуском TCP, потерями пакетов и т. Д.

Блог YUI: исследование производительности, часть 6

Отличный Tomcat 5 Unleashed от Lajos Moczar оказал огромное влияние на мое отношение к разработке полноценного веб-приложения. Это гораздо больше, чем книга о Tomcat. Это дало мне мотивацию, руководство и смелость начать использовать Ant для создания моих JSP-проектов. Ant встроен в NetBeans, мой любимый IDE для JSP, и я привык использовать автоматически сгенерированный файл сборки без необходимости ручного редактирования при создании пакета классов Java. Однако по мере того, как мое понимание JavaScript росло, я обнаружил, что мне нужен процесс сборки, и я был вынужден написать свои собственные файлы конфигурации сборки вручную только для части проекта JavaScript. Moczar build.xml для приложения Tomcat дал мне отличную отправную точку.

Хорошая среда разработки абсолютно необходима для успеха ваших усилий по разработке. Вам нужна структурированная среда, которая позволяет выполнять процессы сборки эффективным и воспроизводимым образом.
— Лайос Мокзар, Tomcat 5 Unleashed

Примечание редактора: если вы решите отказаться от использования Ant, Grunt — фантастический инструмент для сборки ваших JavaScript-приложений. Узнайте больше об этом здесь, на Nettuts +.


Откройте новый проект в NetBeans. Я назвал мой NetTutsBuildJs и создал его в моей папке Nettuts + здесь: C:\NetTuts\BuildJs . Очевидно, что JavaScript не нужно компилировать в exe файл; У нас разные проблемы. Есть как минимум три вещи, которые нам нужны для большого JavaScript-проекта:

  • Разработка исходного кода: создание группы модулей в отдельных файлах. Это наш исходный код.
  • Объединить: собрать все исходные файлы, которые вам нужны для конкретной страницы, и объединить их в один файл.
  • Минимизировать: минимизировать файлы, используя хорошо известный минимизирующий инструмент, чтобы сделать их как можно меньше. Я предпочитаю инструмент YUI Compressor.

Как вы можете видеть на скриншоте, я создал папку с именем js для моего JavaScript, а затем добавил папки src , concat и min .


Мне немного скучно говорить «Hello World» в начале каждого нового урока ИТ, не так ли? Поэтому я подумал, что было бы неплохо игнорировать мир на этот раз. В конце концов, это может быть просто плодом моего воображения!

Я солипсист. Почему нас больше нет?

  • Щелкните правой кнопкой мыши контекстное меню в папке «Исходные файлы» и добавьте новый XML-документ с именем build.xml .
  • Удалите весь текст автоматического шаблона и введите этот текст:
1
2
<project name=»NetTutBuildJs» basedir=».»>
</project>

Вы можете ничего не заметить сейчас, но если вы перезапустите IDE, вы увидите, что build.xml теперь имеет специальный значок с желтым треугольником, связанным с файлами Ant. Если вы выберете его, вы увидите, что панель навигатора теперь отображает цели Муравья в заголовке.

Каждый набор задач в файле сборки Ant называется целью, поэтому нам нужно создать простую цель сообщения
вложенный в тег проекта, например:

1
2
3
<target name=»ignore-world-message»>
    <echo message=»World. You may be a figment of my imagination.»></echo>
</target>

Теперь разверните файл build.xml на панели «Проект», и вы увидите новую цель на панели «Навигатор». Щелкните правой кнопкой мыши на ignore-world-message, и вы увидите сообщение на панели «Вывод», например:


Правильно. Мир может не существовать, и мы его проигнорировали, но, по крайней мере, Ant работает! Помимо шуток, теперь мы должны понять самое важное в Ant правильно: пути.

Я могу быть немного медленным, но у меня всегда были проблемы с этим, поэтому давайте действовать осторожно. Добавьте свойство в начало файла, чуть ниже тега проекта. Вызовите корень свойства и задайте для местоположения строку нулевой длины.

1
<property name=»root» location=»» />

Добавьте новую цель, чтобы отобразить это местоположение, чтобы мы могли убедиться, что у нас есть прямой путь. Обратите внимание на извилистый синтаксис для ссылки на корневое свойство? Вам необходимо заключить имя свойства в двойные кавычки, но, кроме того, вы должны обернуть его знаком доллара и фигурной скобкой слева, а затем закрыть его фигурной скобкой справа. Что за суета!

1
2
3
<target name=»show-root-path»>
<echo message=»${root}»/>
</target>

Вы можете поместить это после цели мира игнорирования. Теперь, когда вы щелкнете правой кнопкой мыши по цели show-root-path чтобы отобразить контекстное меню, а затем щелкните «Run Target», вы должны увидеть правильный путь к корню вашего проекта. В моем случае: C:\NetTuts\BuildJs .


Прекрасный. У нас есть среда, и у нас есть корневой путь, указывающий на правильное место на нашем жестком диске. Теперь мы можем добавить другие пути.

1
2
3
4
<property name=»js» location=»${root}/js» />
<property name=»src» location=»${js}/src» />
<property name=»concat» location=»${js}/concat» />
<property name=»min» location=»${js}/min» />

Наконец, настоящая работа. Мы добавляем новую цель, которая включает тег concat , например так:

1
2
3
4
5
6
7
8
9
<target name=»concat»>
<concat destfile=»${concat}/tree-concat.js» encoding=»UTF-8″ >
<filelist dir=»${src}»
files= «tree_data.js,
tree.js»
>
</filelist>
</concat>
</target>

Это просто тривиальный пример, но для быстроты, чтобы вы могли следить, я создал два простых файла JavaScript: tree_data.js и tree.js , которые зависят от файлов YUI, yahoo-dom-event.js и treeview-min.js tree_data.js имеет следующее довольно бессмысленное содержание:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var treeData = [{
    «label»: «Britain»,
        «children»:[
            «London»,
            «Edinburgh»
        ]
    },{
    «label»: «France»,
        «children»:[
            «Paris»,
            «Lyon»
        ]
    },{
    «label»: «Japan»,
        «children»:[
            «Tokyo»,
            «Kyoto»
        ]
    },{
    «label»: «Thailand»,
        «children»:[
            «Bangkok»,
            «Pattaya»
        ]
}]

И tree.js просто отображает TreeView с tree.js данными.

1
2
3
4
YAHOO.util.Event.onDOMReady(function(){
    var tree = new YAHOO.widget.TreeView(«tree», treeData);
    tree.render();
});

Обратите внимание, что тег filelist — это именно то, что нам нужно. В JavaScript порядок имеет значение, поэтому мы, вероятно, хотим сначала получить данные, а затем — файл рендеринга. Если бы мы использовали тег, который полагался на естественный порядок файлов в операционной системе, мы могли бы получить их в неправильном порядке. Итак, мы старательно печатаем список вручную в теге filelist чтобы обеспечить нужный нам порядок.

Для вас, конечно, есть пуристы: я знаю, что моя переменная treeData является глобальной, и я должен сделать это по-другому. Это просто быстрый пример, чтобы объяснить, как использовать Ant. Я вполне уверен, что люди, которые следуют этому руководству, также следуют современным рекомендациям для своей библиотеки JavaScript.

Теперь запустите цель concat . И вот, файл с именем tree-concat.js волшебным образом появляется в каталоге concat , и когда вы его открываете, вы можете видеть данные, определенные вверху, и функцию рендеринга внизу.

Чтобы попробовать это, я создал два простых html-файла: tree_src.html и tree_concat.html . В заголовке они оба имеют одинаковые ссылки на файлы CSS, необходимые для создания обложки Сэма для TreeView.

1
2
3
<link rel=»stylesheet» href=»js/yui/fonts-min.css»>
<link rel=»stylesheet» href=»js/yui/treeview.css»>
<link rel=»stylesheet» href=»js/yui/treeview-skin.css»>

Прямо перед концом тела в tree_src.html я добавил

1
2
3
4
<script src=»js/yui/yahoo-dom-event.js»></script>
<script src=»js/yui/treeview-min.js»></script>
<script src=»js/src/tree_data.js»></script>
<script src=»js/src/tree.js»></script>

Чтобы проверить объединенный файл. Я изменил теги script в tree_concat.html на:

1
2
3
<script src=»js/yui/yahoo-dom-event.js»></script>
<script src=»js/yui/treeview-min.js»></script>
<script src=»js/concat/tree-concat.js»></script>

Наша древовидная библиотека, кажется, работает, и, когда мы объединяем файлы, мы, кажется, получили правильный порядок. Отлично! Теперь, наконец, пришло время минимизировать все и сократить количество тегов script до одного. Это немного сложнее.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<target name=»min»>
    <apply executable=»java» parallel=»false» dest=»${min}» taskname=»yui»>
        <fileset dir=»${concat}»>
            <patternset>
                <include name=»tree-concat.js»/>
            </patternset>
        </fileset>
        <arg line=»-jar»></arg>
        <arg path=»${compressor}»></arg>
        <arg line=»—charset UTF-8″/>
        <arg line=»-v»></arg>
        <srcfile/>
        <arg line=»-o»></arg>
        <mapper type=»glob» from=»*-concat.js» to=»*-min.js»></mapper>
        <targetfile/>
   </apply>
</target>

Обратите внимание на свойство компрессора. Чтобы все это заработало, я скопировал файл yui_compressor компрессора YUI в папку yui_compressor в моем проекте и создал свойство в файле сборки:

1
<property name=»compressor» location=»${root}/yui_compressor/yuicompressor-2.4.2.jar»/>

Когда мы запускаем цель min , вы должны увидеть этот вывод и новый файл с именем tree-min.js в папке min . Если вы откроете его, вы увидите длинный непрерывный поток JavaScript без пробелов, все в одной строке.

Нужна только еще одна цель: объединить два файла YUI с нашим новым уменьшенным файлом.

01
02
03
04
05
06
07
08
09
10
11
12
13
<target name=»all»>
    <concat destfile=»${min}/all-tree-min.js» encoding=»UTF-8″ >
        <filelist dir=»${yui}»
            files= «yahoo-dom-event.js,
            treeview-min.js»
            >
        </filelist>
        <filelist dir=»${min}»
            files= «tree-min.js»
            >
        </filelist>
    </concat>
</target>

В тестовом файле tree_min.html мне теперь нужен только один тег script :

1
<script src=»js/min/tree-min.js»></script>

Последний шаг — добавить цель, которая вызывает все необходимые цели и запускает их в правильном порядке. Соглашение состоит в том, чтобы назвать эту цель, построить . Также полезно иметь чистую цель для удаления каталогов concat и min и цель init для настройки этих каталогов.

1
2
3
4
5
6
7
8
<target name=»clean»>
    <delete dir=»${concat}»/>
    <delete dir=»${min}»/>
</target>
<target name=»init»>
    <mkdir dir=»${concat}»/>
    <mkdir dir=»${min}»/>
</target>

Теперь цель сборки должна выполняться:

  1. чистый
  2. в этом
  3. CONCAT
  4. мин
  5. все

Чтобы объединить все это, просто добавьте их к атрибуту зависимость, например так.

1
2
<target name=»build» depends=»clean, init, concat, min, all»>
</target>

Мы прошли через шаги, необходимые для создания файла конфигурации для Ant для создания библиотеки JavaScript.

В этом уроке мы рассмотрели шаги, необходимые для создания файла конфигурации для Ant для создания библиотеки JavaScript. Начиная с исходного кода, мы объединили все файлы в библиотеке в один файл, гарантируя, что каждый из исходных файлов будет добавлен в правильном порядке. Мы проверили полученный объединенный файл, чтобы убедиться, что ничего не пропало или неуместно. Затем мы минимизировали этот файл и объединили его с файлами YUI, от которых он зависел.

В результате мы получили веб-страницу с одним тегом script , содержащим весь сложный JavaScript, необходимый для запуска страницы. Я думаю, вы видите, как легко было бы адаптировать этот пример к очень большой сложной библиотеке JavaScript. Используя этот базовый пример в качестве отправной точки, вы сможете изучить документацию Ant и разработать полностью рабочий файл сборки, чтобы автоматизировать каждую часть процесса сборки.

Я также использую Ant для SQL для создания локального клона моей базы данных.

Кроме того, я использую этот тип сборки для CSS-файлов. Они могут стать почти такими же извилистыми, как и файлы JavaScript, и это действительно помогает объединять и минимизировать их. Я также использую Ant для SQL, чтобы создать локальный клон моей базы данных. Я обнаружил, что когда я хочу начать все заново с проекта, вычистив весь экспериментальный код и начав с нуля, очень полезно взять с собой прекрасную свежую новую базу данных. Инструмент Ant позволяет быстро создавать таблицы, функции и процедуры, а затем заполнять их некоторыми примерами данных.