Pull to refresh

Компоненты. Make & watch

Reading time4 min
Views3.6K
в начало заметок о компонентах

make vs. grunt vs. gulp, watch



task runners — класс утилит, автоматизирующих процесс преобразования файлов. Их много, Make, Rake, Cake, etc. Обычно выполняемые задачи очень важны и выполняются часто, и очень часто. Компиляция, запуск тестов, рендеринг и преобразование форматов файлов, минификация js-файлов, преобразование CSS. Крайне важная вещь для ежедневной работы.



grunt (хрюкание). Gruntfile.js — это конфигурационный файл для утилиты grunt. Gruntfile.js интуитивно понятен, одного взгляда на образец достаточно, чтобы создать подобный для своей задачи. Но gruntfile.js крайне уродлив, вдобавок авторы gulp пишут, что grunt крайне неэффективен. Писать, и читать gruntfile.js быстро становится очень скучно.

gulp (глоток «свежего воздуха»). В отличие от gruntfile.js, gulpfile.js является не конфигурационным файлом, а программой на node.js. Посмотрите сравнение двух файлов. Да, это много удобнее и привычнее. Вдобавок, плагины gulp выполняют каждый свою задачу. Например, чтобы минифицировать js-файл, нужно вызвать два плагина, один минифицирует файл, а другой переименует его в файл.min.js. Это правильно. Но размер guplfile.js почти не меньше, чем gruntgile.js, и в десятый раз создавать его столь же унылый процесс. Тем не менее, дело вкуса, но, имхо, gulp много удобнее grunt.

Make же великолепен, и мощен, но Makefile имеет тот недостаток, что он весьма непонятен. Есть либо полное, очень подробное и сухое описание — учебник. Либо множество руководств, пересказывающих один и тот же текст из 1960-х годов прошлого тысячелетия, когда не существовало еще языков программирования, а язык C был еще в разработке. Вот эти замшелые примеры на C и пересказываются. Однако, разобраться в Makefile можно. Это позволит забыть и о grunt, и о gulp. В component-сообществе, как и node-сообществе Makefile очень популярен, поэтому и обсуждается здесь.

Makefile — обзор



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

Макеfile состоит из описания переменных и правил.

target-правила



target-правила в Makefile организованы так:

target: sources
tab -> commands
tab ->tab -> commands, сл. строка той же команды


здесь target — то, что нам нужно получить, sources — массив файлов исходников. Обычно target — это просто файл, за исключением специальных PHONY целей (см. ниже).

Если make встречает ошибку, он прерывает работу. (опция -i игнорировать ошибки).

make использует mtime — время последнего изменения файла. target считается готовым, если во-первых, он уже существует, и во-вторых он новее, чем его исходник. Поэтому make обрабатывает только те файлы, которые изменились.

make начинает с цели-target заданного правила. Если вызвать make без параметра, то это первое правило. Он смотрит исходники, и если для них есть свои правила, рекурсивно проверяет их. Порядок обработки исходников в массиве произвольный!

make идет вниз по цепочке исходников, пока не находит готовой цели, или цели не имеющей исходников, или его исходники не имеют своих правил. Когда он находит такой случай, он возвращается обратно по цепочке рекурсии, выполняя соответствующие команды. make создает цепочки рекурсии для каждого исходника.

правила нужно разделять пустой строкой.

pattern правила



pattern правила описывают, что делать с конкретным расширением, и имеют вид:

%.js: %.html
        @component convert $<;


phony — правила



phony-правила — это не файлы, а команды. Они могут иметь исходники, рекурсию и все, что имеют другие правила, но для них не вычисляется mtime. Например:

clean:
        rm -fr build components $(TEMPLATES)

.PHONY: clean


phony-правила нужно описать в специальной переменной .PHONY

описание переменных



Есть автоматические, предзаданные переменные, их нужно понимать. Вот несколько часто встречающихся $@ — имя цели, $+ — все исходники, через пробел, $<; — имя первого исходника. Полный список в учебнике — http://www.gnu.org/software/make/manual/make.html#Automatic-Variables

Обычные переменные (файлы, требующие обработки, цели, имеющие файлы в исходниках) — можно просто перечислить

JS = index.js example.js


но часто удобно их вычислять с помощью shell:

CF = $(shell find templates -name "*.coffee")


или с помощью встроенной утилиты wildcard:

SRC = $(wildcard client/*/*.js)


Или определить targets из уже созданной переменной:

HTML = $(JADE: .jade=.html)


В последнем случае сами html-файлы пока не создаются, но только массив их имен для дальнейшей обработки.

примеры задания переменных и правил:



SRC = $(wildcard client/*/*.js)
HTML = $(wildcard client/*/*.html)
TEMPLATES = $(HTML:.html=.js)

build: components $(SRC) $(TEMPLATES)
        @component build

components: component.json
        @component install

%.js: %.html
        @component convert $<;


Что здесь происходит? make встречает имя components, обнаруживает такую директорию, и если мы внесли изменения в файл component.json, выполняет install.

Далее он переходит к SRC, это массив файлов JS. Он смотрит 'исходники' первого файла .js, находит pattern-правило для .js и выполняет его из исходника .html. Затем собирает все в единый build/build.js см. component build, component convert.

еще пример:

JADE = $(shell find templates -name "*.jade")
HTML = $(JADE:.jade=.html)

all: $(HTML)

%.html: %.jade
    jade < $< > $@


пример pattern-правил — обработать coffee, jade:

%.js: %.coffee
  @coffee -c $<

%.js: %.jade
  @jade -c $<


Естественно, утилиты coffee, jade должны быть установлены в системе.

watch



watch — это не компонента, не node.js утилита, а обычная unix-утилита. (Странно, что ее нет в Altlinux, например).

клонируем и ставим ее:

$ PREFIX=~ make install


и запускаем make

$ watch make &;


Сравните с тем, что нужно сделать для отслеживания изменений в исходниках, и авто-перекомпиляции в grunt. В gulp эта функциональность встроенно в ядро, а не является плагином. Но от этого не легче, чтобы запустить ее в gulpfile.js. Даже не хочется приводить пример кода.

В Makefile можно организовать то же самое и без утилиты watch:

.PHONY: continuously
continuously:
    while true; do make 1>/dev/null; sleep 3; done


продолжение следует
Tags:
Hubs:
-12
Comments1

Articles