Gulp-файл для frontend проекта
Решение не претендует на идеальность. Но вполне подойдет для разработки небольшого frontend проекта, написанного с использованием coffeescript и less. Важное замечание: использование бекенда не предусмотрено. Nodejs использован только для билда ассетов (такое решение удобно, к примеру, если вы планируете создать гибридное оффлайн приложение для смартфона).
Ключевые особенности нашего проекта, и, как следствие, gulp-файла:
1) Поддерживает разные среды (prod, dev, etc)
2) Компиляция и минификация less, CoffeScript файлов, объединение нескольких в один (конкатенация)
3) Поддержка тестов (jasmine)
4) В dev-среде работает watch (динамически перебилдивает ассеты при изменении исходников)
У проекта следующая структура (лишнее не отображаю):
.
├── css
├── js
├── node_modules
├── public
│ ├── bower_components
│ ├── css
│ ├── img
│ └── js
└── spec
Исходники располагаются в css, js директориях (те, которые в корне). В public лежит все, что уже готово к отображению: index.html файл, скомпиленные ассеты. Директория spec - для jasmine тестов.
Более подробно о построении gulpfile:
Список используемых модулей:
var gulp = require('gulp'),
less = require('gulp-less'),
coffee = require('gulp-coffee'),
concat = require('gulp-concat'),
watch = require('gulp-watch'),
batch = require('gulp-batch'),
fs = require('fs'),
argv = require('yargs').argv
;
Для начала, определим среду:
// Environment detecting
var env = argv.env || 'prod',
envFile = '.env'
;
if (!argv.env && fs.existsSync(envFile)) {
env = fs.readFileSync(envFile, 'utf8');
}
Как видим, среда определяется либо аргументом команды gulp, либо содержимым envFile (у меня envFile - файл .env в корне проекта).
Добавим сборку .less файлов:
gulp.task('less', function () {
gulp.src('./css/**/*.less')
.pipe(less())
.pipe(concat('style.css'))
.pipe(gulp.dest('./public/css/'))
;
});
Обратите внимание на маску: таким образом, будут собираться рекурсивно все файлы в директории ./css
Добавим сборку .coffee файлов. Здесь немного сложнее. Дело в том, что удобно разделить исходники (назовем их "библиотеки") и скрипт запуска приложения. Это нужно, к примеру, для запуска тестов.
gulp.task('coffee-lib', function () {
gulp.src(['./js/**/*.coffee', '!./js/app.coffee'])
.pipe(coffee())
.pipe(concat('lib.js'))
.pipe(gulp.dest('./public/js/'))
;
});
gulp.task('coffee-app', function () {
gulp.src('./js/app.coffee')
.pipe(coffee())
.pipe(concat('app.js'))
.pipe(gulp.dest('./public/js/'))
;
});
Как видите, в таске coffee-lib исключен файл ./js/app.coffee.
Добавим таск для тестов:
gulp.task('coffee-spec-common', function () {
gulp.src('./spec/common.coffee')
.pipe(coffee())
.pipe(concat('spec-common.js'))
.pipe(gulp.dest('./public/js/'))
;
});
gulp.task('coffee-spec', function () {
gulp.src(['./spec/**/*.coffee', '!./spec/common.coffee'])
.pipe(coffee())
.pipe(concat('spec.js'))
.pipe(gulp.dest('./public/js/'))
;
});
coffee-spec-common таск компилит общие утилиты для тестов (у меня, к примеру, там находятся методы, проверяющие равность двухмерных массивов и другие) вынесен отдельно для того, чтобы гарантировать подключение перед тестами.
Добавим watch и batch для удобства разработки:
gulp.task('watch', function() {
watch(['./js/**/*.coffee'], batch(function(events, cb) {
gulp.start('default', cb);
}));
watch(['./spec/**/*.coffee'], batch(function(events, cb) {
gulp.start('default', cb);
}));
watch(['./css/**/*.less'], batch(function(events, cb) {
gulp.start('default', cb);
}));
});
(Batch добавляет задержку перед перекомпиляцией. Он устраняет проблему с производительностью при переключении веток в git).
Добавим watch в дев режиме и главный таск:
var tasks = ['coffee-lib', 'coffee-app', 'less'];
if (env === 'dev') {
tasks.push('watch');
tasks.push('coffee-spec-common');
tasks.push('coffee-spec');
}
gulp.task('default', tasks);
Полный пример можно посмотреть здесь