Здесь видео и код к скрикастам. "Система достаточно детская, но надо же с чего-то начинать" (- Илья Кантор). А этот пост начинается ссылками на подборки статей, потом я постарался привязать примеры к видео поминутно..., а заканчиватся все фрагментами кода из двадцатиминутного ролика "Начальная сборка стилей" и последующим копипастом заголовков "Рецептов" из документации Gulp
gulp-screencast/03-vinyl/gulpfile.js
gulp/docs/getting-started.md
Recipes
gulp API docs
minimatch This is the matching library used internally by npm.
globtester.com a little utility for testing minimatch
gulp-if A ternary gulp plugin: conditionally control the flow of vinyl objects
Четыре способа возврата данных
'use strict';
const gulp = require('gulp');
gulp.task('hello', function(callback) {
console.log("Hello");
callback();
});
gulp.task('example:promise', function() {
return new Promise((resolve, reject) => {
// ...
resolve('result');
});
});
gulp.task('example:stream', function() {
// reads all from stream (and throws the data away) and then done
return require('fs').createReadStream(__filename);
});
gulp.task('example:process', function() {
// returns child process
return require('child_process').spawn('ls', ['.'], {stdio: 'inherit'});
});
gulp.task('example', gulp.parallel('hello', 'example:promise', 'example:stream',
'example:process'));
Копируем файлы в dest рекурсивно¶
# .on('data', function(file) { //обработчик для просмотра свойств каждого файла
# Путь - до звездочек - base, а потом -relative
# .pipe(gulp.dest(function('dest')))
# в пайпе для кажого файла заменяется base
# и все папки с подпапками копируются рекурсивно
# .pipe(gulp.dest(function(file) { //а можно использовать функцию - см. ниже
# - 6-ая минута Gulp 3: Потоки Vinyl-FS
'use strict';
const gulp = require('gulp');
gulp.task('default', function() {
return gulp.src('source/**/*.*')
.on('data', function(file) {
console.log({
contents: file.contents,
path: file.path,
cwd: file.cwd,
base: file.base,
// path component helpers
relative: file.relative,
dirname: file.dirname, // .../source/1
basename: file.basename, // 1.js
stem: file.stem, // 1
extname: file.extname // .js
});
})
.pipe(gulp.dest(function(file) {
return file.extname == '.js' ? 'js' :
file.extname == '.css' ? 'css' : 'dest';
}));
});
А как выбрать файлы из папок source (усложним пример выше)¶
# return gulp.src('source/**/*.*')
# ... gulp.src('{source1,source2}/**/*.{js,css}') // без пробелов после запятой !!!
# ... gulp.src(['source/**/*.js','source/**/*.css']) // если js надо обработать первыми
# ... gulp.src('**/*.*','!node_modules/**') //Опасно, не рекомендуется
В последнем варианте нужно будет просматривать подпапки node_modules, огромные потери времени (10-я минута Gulp 3: Потоки Vinyl-FS)
Не читать содержание файлов {read:false})¶
# return gulp.src(['source/**/*.*', 'gulpfile.js','pacaje.json'], {read:false})
Содержание file.contents - это буфер, либо null (13 минута Gulp 3: Потоки Vinyl-FS)
####Можно задать текущую директорию cwd специальной опцией... (но пример надо искать самим)
cwd =/my/project
Видео про стили gulp-screencast/04-styles-1/gulpfile.js¶
'use strict';
const gulp = require('gulp');
const stylus = require('gulp-stylus');
const concat = require('gulp-concat');
const debug = require('gulp-debug');
gulp.task('styles', function() {
return gulp.src('frontend/**/*.styl')
.pipe(debug({title: 'src'}))
.pipe(stylus())
.pipe(debug({title: 'stylus'}))
.pipe(concat('all.css'))
.pipe(debug({title: 'concat'}))
.pipe(gulp.dest('public'));
});
Это файл настроен для вот для этих папок:
F:\stradorusite\GULP-projects\gulp-screencast\04-styles-1>tree /F
F:.
│ gulpfile.js
│ package.json
│
├───frontend
│ ├───assets
│ │ │ index.html
│ │ │
│ │ └───img
│ │ cat.svg
│ │
│ └───styles
│ header.styl
│ main.styl
│
└───public
main.css
Разрабатываем в папке frontend, а "раздаем" статические файлы из public (здесь у него лежка deploy)
# Помнить про то, что асинхронные задачи - это незавершенные задачи
# и ждут команды на завершение? ... нужно вернуть один из 4-х вариантов
# callback, поток, обещание, ...
process.on('exit')
# Did you forget to signal async completion?
# return gulp.src( // возвращает поток
#(4-ая минута Gulp 4: Начальная сборка стилей)
###Обычные варианты с путями файлов
можно явно указать base, и тогда файлы запишутся в public/styles, а не в public
return gulp.src('frontend/styles/**/*.styl', {base:'frontend'})
#(6-ая минута Gulp 4: Начальная сборка стилей)
В данном случае проще не мудрить, а получить тоже самое вот так
return gulp.src('frontend/**/*.styl')
#### Gulp-debug "все через себя пропускает и выводит, что через него проходит"
####Порядок конкатенции стилей нам не гарантирован
.pipe(concat('all.css'))
#(10-ая минута Gulp 4: Начальная сборка стилей)
Поэтому в frontend нужно создавать главнй файл main.styl, прописать команды импорта внутри него, а потом обрабатывать (компилировать, минимизировать...) только его... вместо конкатенции.
Следующий файл для того же скринкаста gulp-screencast/04-styles-2/gulpfile.js¶
Речь пошла о sourcemaps, он создает новое свойство file.sourcemap - путь к входящему файлу. Поскольку это плагин от разработчиков Gulp, то все разработчики других плагинов знают про него и используют
(11-ая минута Gulp 4: Начальная сборка стилей)¶
# Включить отслеживание первоисточника
sourcemaps.init()
sourcemaps.write()
# Записывает строчку base64 в конец выходного файла директории public
# main.css
sourcemaps.write('.')
# Записывает результат в новый файл в той же директории public
# main.css.map
# но в main.css добавляется строчка
/*# sourceMapURL main.css.map*/
#(14-ая минута Gulp 4: Начальная сборка стилей)
'use strict';
const gulp = require('gulp');
const stylus = require('gulp-stylus');
const sourcemaps = require('gulp-sourcemaps');
const debug = require('gulp-debug');
const isDevelopment = !process.env.NODE_ENV || process.env.NODE_ENV == 'development';
gulp.task('styles', function() {
let pipeline = gulp.src('frontend/styles/main.styl');
if (isDevelopment) {
pipeline = pipeline.pipe(sourcemaps.init());
}
pipeline = pipeline
.pipe(stylus());
if (isDevelopment) {
pipeline = pipeline.pipe(sourcemaps.write());
}
return pipeline
.pipe(gulp.dest('public'));
});
Здесь пример того, как использовать условие в сборке для вариантов разработки и эксплуатации... Зачем нам на "боевом сайте" sourcemaps? Потому запустить "продакшен" сборку можно будет как-то так:
> NODE_ENV=production gulp styles
"Не очень красиво, но работает, проще использовать плагин..."
Третий файл к скринкасту gulp-screencast/04-styles-3/gulpfile.js¶
Подключаем плагин Gulp-if
(17-ая минута Gulp 4: Начальная сборка стилей)¶
'use strict';
const gulp = require('gulp');
const stylus = require('gulp-stylus');
const sourcemaps = require('gulp-sourcemaps');
const debug = require('gulp-debug');
const gulpIf = require('gulp-if');
const del = require('del');
const isDevelopment = !process.env.NODE_ENV || process.env.NODE_ENV == 'development';
gulp.task('styles', function() {
return gulp.src('frontend/styles/main.styl')
.pipe(gulpIf(isDevelopment, sourcemaps.init()))
.pipe(stylus())
.pipe(gulpIf(isDevelopment, sourcemaps.write()))
.pipe(gulp.dest('public'));
});
gulp.task('clean', function() {
return del('public');
});
gulp.task('assets', function() {
return gulp.src('frontend/assets/**')
.pipe(gulp.dest('public'));
});
gulp.task('build', gulp.series(
'clean',
gulp.parallel('styles', 'assets'))
);
Возможности плагина очень велики. Например, для каждого файла можно указать, пропускать , или не пропускать его через поток...
.pipe(gulpIf(function(file) {
return file.extname =='.js'
}, sourcemaps.init()))
Плагин gulp-del возвращает Promise, del('public') - это не плагин, а модуль общео назначения
gulp.task('clean', function() {
return del('public');
});
О сериях и параллельных задачах - сначала выполняется clean, а потом две паралельных (одновременных асинхронных) задачи.
(21-ая минута Gulp 4: Начальная сборка стилей)¶
gulp.task('build', gulp.series(
'clean',
gulp.parallel('styles', 'assets'))
);
Как поставить сервер¶
> npm i -g node-static
> static
#(22-ая минута Gulp 4: Начальная сборка стилей)
Automate release workflow
Combining streams to handle errors
Delete files and folders
Fast browserify builds with watchify
Incremental rebuilding, including operating on full file sets
Make stream from buffer (memory contents)
Mocha test-runner with gulp
Only pass through changed files
Pass parameters from the command line
Rebuild only files that change
Generating a file per folder
Running tasks in series
Server with live-reloading and CSS injection
Sharing streams with stream factories
Specifying a new cwd (current working directory)
Split tasks across multiple files
Using external config file
Using multiple sources in one task
Browserify + Uglify with sourcemaps
Browserify + Globs
Browserify + Globs (multiple destination)
Output both a minified and non-minified version
Templating with Swig and YAML front-matter
Run Grunt Tasks from Gulp
Exports as tasks
Rollup with rollup-stream
Tagtree intro to gulp video
Introduction to node.js streams
Video introduction to node.js streams
Getting started with gulp (by @markgdyr)
A cheatsheet for gulp
Why you shouldn’t create a gulp plugin (or, how to
stop worrying and learn to love existing node packages)
Inspiration (slides) about why gulp was made
Building With Gulp
Gulp - The Basics (screencast)
Get started with gulp (video series)
Optimize your web code with gulp
Automate Your Tasks Easily with Gulp.js
Посты чуть ниже также могут вас заинтересовать
Комментариев нет:
Отправить комментарий