Блог Мазепина Василия

Пишу о том, что кажется интересным

Здравствуй, Gulp

2016-08-31 21:10 | Комментарии

Доброго времени суток, коллеги и гости. Хотелось бы поделиться результатами своих результатов в изучении такого инструмента, как Gulp .

С чего всё начиналось

Мне, по нужде сугубо рабочей, понадобилось развернуть E-Commerce систему “Sylius” , написанную на php с использованием Symfony Framework. Однако, установив все зависимости, я обнаружил, что скрипты и стили не подгружены, хотя у Symfony есть система, работающая со скриптами. И как только я полез в документацию по установке этого самого Sylius, я обнаружил, что для работы скриптов необходимо запустить утилиту gulp в директории проекта. После этого я стал изучать - что же это за зверь такой. Прошлая версия Sylius'a то и без него прекрасно работала. В итоге, изучив несколько страниц документации, Sylius заработал как положено. Однако, набравшись впечатлений от работы gulp'a, я решил поизучать некоторые его возможности и рассказать о них Вам.

Какую проблему решаем?

Gulp выполняет по сути одну задачу - он сборщик скриптов. Он может собрать стили, скрипты, перепарсить какие нибудь markdown, скомпилировать, что потребуется.

Какие возможности имеем?

Имея за спиной огромное множество пакетов(плагинов) , gulp имеет кучу возможностей, перечислю несколько:

  • Компилирование стилей(LESS, SaSS), скрипты(Typescript), отправляя результат в нужную директорию
  • Сборка несколько файлов в один, что очень экономит количество тегов подключений в вашем HTML
  • Минификация файлов(скриптов, стилей).
  • Обфускация скриптов
  • Разворачивание локального web-сервера
  • Работа с файловой системой
  • Отслеживание изменений файлов “на лету”, с последующей обработкой сего события

Это далеко не все возможности, так как плагинов, повторюсь - огромное количество .

С чего начнем?

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

  • Typescript
  • JS
  • CSS
  • SaSS

Так же в тестовом проекте были использованы вендорные стили и скрипты от Bootstrap, и Jquery. Чисто для примера.

Установка

Важно сказать, что gulp - программа на nodejs, поэтому для ее установки необходимо иметь npm. Устанавливаем:

Установка - Терминал
1
$ npm install gulp --global # Можно ставить и не глобально, тут выбор сугубо ваш

Далее, необходимо понимать, что скорее всего работа вашего сборщика, будет происходить при помощи плагинов, которые являются npm - зависимостями. Поэтому:

Инициализация проекта - Терминал
1
2
$ npm init
$ npm install --save gulp # Это поможет, в случае если gulp придется ставить внутри проекта, мало ли, вдруг вам прав не дали на глобальные установки

И тут пошла магия!

Механика использования скрипта проста - при вызове внутри проекта команды gulp, утилита запускает файл ‘gulpfile.js’, В которой и прописывается вся магия

gulpfile.js
1
2
3
4
5
var gulp = require('gulp');

gulp.task('default', function() {
  // вставьте ваш магический код
});

Обратите внимание, есть метод gulp.task(), то есть инициализируется именованная задача, которую можно вызвать:

Запуск задачи - Терминал
1
$ gulp default

Важно отметить, что по умолчанию, при вызове gulp без указания имени задачи, будет выполнена задача с именем ‘default’

Никакой магии, только код

Выделим задачи, которые необходимо выполнить нашему сборщику:

  1. Скомпилировать стили
  2. Скомпилировать Typescript
  3. Собрать все стили в один файл
  4. Собрать все скрипты в один файл
  5. Минифицировать стили
  6. Минифицировать скрипты
  7. Удалить временные файлы, если имеются

Важно отметить, что в ходе компиляций Gulp позволяет в одной задаче выполнять другую задачу, поэтому создадим под каждый пункт по задаче, после чего в задаче ‘default’ выполним все пункты.

1. Скомпилировать стили
1
2
3
4
5
6
7
8
9
...
var sass = require('gulp-sass');

gulp.task('sass-build', function(){
    return gulp.src('./sass/*.scss')
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest(tmpDir));
});
...
2. Скомпилировать Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
...
var ts = require('gulp-typescript');
var tsResult = gulp.src(
        [
            'ts/*.ts'
        ]
    )
        .pipe(ts({
            noImplicitAny: true,
            out: 'typescript.js'
        }));
     return tsResult.js.pipe(gulp.dest(tmpDir));
...
3. Собрать все стили в один файл
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
var concat = require('gulp-concat');

gulp.task('concat-css', function() {
    return gulp.src(
        [
            'bower_components/bootstrap/dist/css/bootstrap.min.css',
            'tmp/*.css',
            'css/*.css'
        ]
    )
        .pipe(concat('app.css'))
        .pipe(gulp.dest(scriptsDir));
});
...
4. Собрать все скрипты в один файл
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...
var concat = require('gulp-concat');

gulp.task('concat-js', function() {
    return gulp.src(
        [
            'bower_components/jquery/dist/jquery.min.js',
            'bower_components/bootstrap/dist/js/bootstrap.min.js',
            'tmp/*.js',
            'js/*.js'
        ]
    )
        .pipe(concat('app.js'))
        .pipe(gulp.dest(scriptsDir));
});
...
5. Минифицировать стили
1
2
3
4
5
6
7
8
9
...
var minifyCss = require('gulp-clean-css');

gulp.task('minify-css', function(){
    return gulp.src(scriptsDir + '/app.css')
        .pipe(minifyCss({debug: false}))
        .pipe(gulp.dest(scriptsDir));
});
...
6. Минифицировать скрипты
1
2
3
4
5
6
7
8
9
...
var minifyJs = require('gulp-minify');

gulp.task('minify-js', function(){
    return gulp.src(scriptsDir + '/app.js')
        .pipe(minifyJs())
        .pipe(gulp.dest(scriptsDir));
});
...
7. Удалить временные файлы
1
2
3
4
5
6
7
...
var clean = require( 'gulp-clean');
gulp.task('clean', function() {
     return gulp.src([tmpDir, scriptsDir + '/app.js'], { read: false })
         .pipe( clean({force:true}) )
});
...

Теперь осталось настроить таск ‘default’, который, собственно, и запустит указанные таски. Важно отметить, что в документации описана возможность запуска заданий вот так:

Запуск заданий
1
2
3
gulp.task(
    'default', ['task1', 'task2', 'task3', 'task4', ...]
);

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

Однако некоторые задачи мы распараллелить все-таки можем. Вот так:

  1. ‘sass-build’ + ‘ts-build’
  2. ‘concat-css’ + ‘concat-js’
  3. ‘minify-css’ + ‘minify-js’
  4. ‘clean’

Поискав на просторах инета решение проблемы, нашел плагин ‘gulp-sequence’, и решение оказалось таким:

gulpfile.js
1
2
3
4
5
6
7
8
9
10
11
12
var sequence = require('gulp-sequence');

gulp.task(
    'default',
    sequence(
        ['sass-build', 'ts-build'],
        ['concat-css', 'concat-js'],
        ['minify-css', 'minify-js'],
        'clean'
    )
);
...

Плагин позволяет нам запускать задачи, указывая последовательность, а также указывая, какие задачи следует распараллелить. И такая схема более чем рабочая: мы параллельно компилим скрипты со стилями, далее параллельно их собираем, потом параллельно их минифицируем, и только в конце чистим за собой. Красота!

К чему пришли ?

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

Спасибо за внимание! Спишемся.

Комментарии