Современная сборка 2020 для frontend. gulp4
Содержание:
Введение
Gulp — это таск-менеджер для автоматического выполнения часто используемых задач
(например, минификации, тестирования, объединения файлов), написанный на
языке программирования JavaScript.
Программное обеспечение использует
командную строку для запуска задач, определённых в файле Gulpfile.
Создан как ответвление от проекта Grunt, чтоб взять из него лучшие практики.
Распространяется через менеджер пакетов
NPM
под MIT лицензией.
Если Вы будете копировать код с этой страницы — имейте в виду, что я ставлю кое-где лишние
проблелы — исключительно для того, чтобы текст лучше помещался на экран. Смело удаляйте их.
Это основная статья об использовании Gulp.
В данный момент Вы можете помимо этой прочитать также статьи:
Как скопировать папку с помощью Gulp |
|
Объединить и сжать несколько css файлов в один |
|
Как отправить файлы по ftp с помощью Gulp |
|
Gulp series |
|
Обработка только изменённых файлов с помощью gulp.watch().on(‘change’) |
Issues
If you have a feature request/question how Sass works/concerns on how your Sass gets compiled/errors in your compiling, it’s likely a Dart Sass or LibSass issue and you should file your issue with one of those projects.
If you’re having problems with the options you’re passing in, it’s likely a Dart Sass or Node Sass issue and you should file your issue with one of those projects.
We may, in the course of resolving issues, direct you to one of these other projects. If we do so, please follow up by searching that project’s issue queue (both open and closed) for your problem and, if it doesn’t exist, filing an issue with them.
Создание проекта
Двигаемся дальше. Теперь создайте папку проекта в удобном месте вашего компьютера. Назовем ее, например, gproject.
Перейдем в папку проекта и запустим консоль команд для данного каталога. Наиболее быстрый вариант сделать это зажать клавишу «Shift» и удерживая ее щелкнуть правой кнопкой мыши на пустой области окна каталога. Откроется контекстное меню, в котором выбираем «Открываем окно PowerShell здесь«. Данный пункт может называться и по другому — «Открыть окно команд«.
Запускаем инициализацию проекта командой:
Заполняем необходимые поля проекта по шагам и желательно латиницей. После ввода названия жмем Enter и переходим с следующему шагу.
- package-name: вводим название проекта маленькими буквами
- version: оставляем по умолчанию — 1.0.0
- description: вводим описание проекта, например, My first gulp project.
- entry point: (index.js), test command:, git repository:, keywords: — данные шаги оставляем по умолчанию, жмем Enter и переходим к следующему шагу
- author: впишите имя автора, я ввел Zaur Magomedov
- license: оставляем по умолчанию
- Is this ok? — вводим «yes» и жмем Enter поле чего в папке нашего проекта появится файл package.json.
Файл package.json содержит в себе информацию о проекте + информацию об установленных пакетах (плагинов). Это своего рода файл манифеста. Теперь давайте установим Gulp локально в папку нашего проекта. Для этого пишем следующую команду:
флаг —save-dev как раз говорит установщику установить gulp локально в папку нашего проекта.
При установке gulp название пакета и его версия автоматически пропишутся в файле package.json. Вообще такой подход позволяет сохранять файл package.json со всеми установленными пакетами (зависимости), а при разворачивании нового проекта достаточно скопировать данный файл и запустить команду установки в консоли проекта — и все пакеты в проект установятся автоматически. Сейчас может вам будет не совсем понятно, но дальше я уверен вы поймете.
И так, после установки gulp в папке проекта должна появиться папка node_modules, она содержит в себе необходимые зависимости. Также все новые установленные зависимости, прописываемые в package.json будут складываться именно в данную папку. Так что ничего не трогайте в ней и не удаляйте. Не пугайтесь если увидите в ней много файлов и папок.
Давайте откроем файл package.json реактором кода и взглянем на его содержимое.
Мы видим всю ту информацию, которую вводили при инициализации проекта + ниже в блоке «devDependencies» указаны установленные зависимости и их версии. В данном случае это gulp версии 3.9.1. Как я и говорил установилась локально именно та версия, что стоит глобально.
Sample gulpfile.js
This file is just a quick sample to give you a taste of what gulp does.
var gulp =require('gulp4');var less =require('gulp-less');var babel =require('gulp-babel');var concat =require('gulp-concat');var uglify =require('gulp-uglify');var rename =require('gulp-rename');var cleanCSS =require('gulp-clean-css');var del =require('del');var paths ={ styles{ src'src/styles/**/*.less', dest'assets/styles/'}, scripts{ src'src/scripts/**/*.js', dest'assets/scripts/'}};functionclean(){returndel('assets');}functionstyles(){returngulp.src(paths.styles.src).pipe(less()).pipe(cleanCSS()).pipe(rename({ basename'main', suffix'.min'})).pipe(gulp.dest(paths.styles.dest));}functionscripts(){returngulp.src(paths.scripts.src,{ sourcemapstrue}).pipe(babel()).pipe(uglify()).pipe(concat('main.min.js')).pipe(gulp.dest(paths.scripts.dest));}functionwatch(){gulp.watch(paths.scripts.src, scripts);gulp.watch(paths.styles.src, styles);}exports.clean= clean;exports.styles= styles;exports.scripts= scripts;exports.watch= watch;var build =gulp.series(clean,gulp.parallel(styles, scripts));gulp.task('build', build);gulp.task('default', build);
Методы gulp
Мы уже видели в коде выше метод series — который позволяет выполнять перечисляемые задачи последовательно (следующая задача выполняется только после завершения предыдущей). Постепенно мы рассмотрим все методы Gulp.
- src — какие файлы использовать для обработки в потоке;
- dest — куда выгружать обработанные в потоке файлы (место назначения);
- watch — наблюдение за изменениями в файлах;
- series — вызов задач последовательно;
- parallel — вызов задач параллельно.
Как создавать задачи мы рассмотрели. Теперь рассмотрим, как выбирать необходимые файлы.
Gulp src / dest
Сначала рассмотрим пример, затем уже разберём какие паттерны (выборки) для выбора файлов можно использовать.
В данном примере мы видим работу двух методов:
- src (source) — выбираем файлы для обработки;
- dest (destination) — место назначения.
В src мы использовали паттерн css/**.css для выбора всех css файлов внутри папки /assets/css/ (исключая файлы в подпапках, если таковые имеются).
Примеры наиболее используемых паттернов для выбора файлов:
- app/**/*.* — выбор всех файлов в папке app;
- app/js/**/*.js — выбор всех js файлов в папке js;
- app/**/*.{css,js} — все css и js файлы в папке app;
- app/{folder1,folder2}/**/*.{js,css} — все js и css-файлы в папках folder1 и folder2;
- [‘app/**/*.css’, ‘app/**/*.js’] — получаем сначала все css, потом все js в папке app;
- [‘app/**/*.*’, ‘!app/**/*.js’] — все файлы в папке app, кроме js-файлов. (! — знак исключения).
Gulp series / parallel
В нашем примере была указана одна функция, но задач в gulp может быть очень много. Чтобы выполнять все перечисленные функции одной командой gulp необходимо сделать следующее.
В series мы перечисляем список задач для последовательного выполнения.
Если нам не важно когда закончится та или иная задача, мы можем использовать метод parallel:
В данном примере, сначала выполнится задача output, затем последовательно будут выполняться otherFunc и otherFunc2, и после их завершения начнёт своё выполнение задача otherFunc3.
Gulp lastRun()
Используется для ускорения времени выполнения, за счёт пропуска файлов, которые не изменились с момента последнего успешного завершения задачи.
Пример:
works great with lazypipe
Lazypipe creates a function that initializes the pipe chain on use. This allows you to create a chain of events inside the gulp-if condition. This scenario will run jshint analysis and reporter only if the linting flag is true.
var gulpif =require('gulp-if');var jshint =require('gulp-jshint');var uglify =require('gulp-uglify');var lazypipe =require('lazypipe');var linting =false;var compressing =false;var jshintChannel =lazypipe().pipe(jshint).pipe(jshint.reporter).pipe(jshint.reporter,'fail');gulp.task('scripts',function(){returngulp.src(paths.scripts.src).pipe(gulpif(linting,jshintChannel())).pipe(gulpif(compressing,uglify())).pipe(gulp.dest(paths.scripts.dest));});
Отслеживание файлов
Gulp имеет возможность следить за изменением файлов и выполнять задачу или задачи при обнаружении изменений. Эта функция удивительно полезна (для меня, наверное, одна из самых полезных в Gulp). Вы можете сохранить Less-файл, а Gulp превратит его в CSS и обновит браузер без каких-либо действий с вашей стороны.
Для слежения за файлом или файлами используйте функцию gulp.watch(), которая принимает шаблон файлов или их массив (такой как gulp.src()), либо массив задач для их запуска или выполнения функции обратного вызова.
Предположим, что у нас есть задача build, она превращает наши файлы шаблонов в HTML и мы хотим определить задачу watch, которая отслеживает изменение шаблонов и запускает задачу для преобразования их в HTML. Мы можем использовать функцию watch следующим образом:
Теперь при изменении файла шаблона будет запущена задача build, которая создаст HTML.
Вы также можете указать для watch функцию обратного вызова вместо массива задач. В этом случае функция получает объект event содержащий информацию о событии, которое вызвало функцию:
Другой отличительной особенностью gulp.watch() является то, что она возвращает watcher. Используйте его для прослушивания дополнительных событий или для добавления файлов в watch. Например, чтобы одновременно запустить список задач и вызвать функцию, вы можете добавить слушателя в событие change при возвращении watcher:
В дополнение к событию change вы можете прослушивать ряд других событий:
- end
Срабатывает, когда watcher завершается (это означает, что задачи и функции обратного вызова не будут больше вызываться при изменении файлов).
- error
Срабатывает, когда происходит ошибка.
- ready
Срабатывает, когда файлы были найдены и готовы к отслеживанию.
- nomatch
Срабатывает, когда запросу не соответствует ни один файл.
Объект watcher также содержит некоторые методы, которые можно вызывать:
- watcher.end()
Останавливает watcher (при этом задачи или функции обратных вызовов не будут больше вызываться).
- watcher.files()
Возвращает список файлов за которыми следит watcher.
- watcher.add(glob)
Добавляет файлы в watcher, которые соответствуют указанному шаблону glob (также принимает необязательную функцию обратного вызова в качестве второго аргумента). - watcher.remove(filepath)
Удаляет определённый файл из watcher.
Gulp
Writing a task
The tasks present in gulp-setup are made out of two components: and . All other parameters, such as , are made available in these components.
constsetup=require('gulp-setup')($, gulp,{ tasks{'mytask'{ base'./bases/base', process'./tasks/mytask', pattern'**/*.css', paths{ src'path/to/custom-src', build'path/to/custom-build', dist'path/to/custom-dist'}}}});
The task serves as a template for other tasks. It makes four pipeline hooks available: , , dist and for integrating a process into it. If the task is missing, then the is considered as a standalone task and won’t use a template.
module.exports=($,gulp,config,task)=>()=>gulp.src($.path.join(config.task.src||config.paths.src,task.pattern)).pipe(task.process.init()).pipe($.debug()).pipe(task.process.build()).pipe(gulp.dest(config.task.build||config.paths.build)).pipe(task.process.dist()).pipe(gulp.dest(config.task.dist||config.paths.dist)).pipe(task.process.end());
The gulp-setup package provides you with the following premade bases: , and . You can use these bases for your custom process tasks.
The process task is the main processing that the task is concerned with. Process tasks normally use a template, a task that they integrate with by providing , , or hooks. Alternatively, you can write the process as a standalone gulp task.
Template
module.exports=($,gulp,config,task)=>({ build$.lazypipe().pipe($.autoprefixer), dist$.lazypipe().pipe($.cssmin)});
Standalone
module.exports=($,gulp,config,task)=>{return()=>gulp.src(config.paths.build,config.paths.dist).pipe($.clean());}
LICENSE
(MIT License)
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
«Software»), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Use last JavaScript version in your gulpfile
Node already supports a lot of ES2015, to avoid compatibility problem we suggest to install Babel and rename your as .
npm install --save-dev babel-register babel-preset-es2015
Then create a .babelrc file with the preset configuration.
{"presets""es2015"}
And here’s the same sample from above written in ES2015.
importgulpfrom'gulp';importlessfrom'gulp-less';importbabelfrom'gulp-babel';importconcatfrom'gulp-concat';importuglifyfrom'gulp-uglify';importrenamefrom'gulp-rename';importcleanCSSfrom'gulp-clean-css';importdelfrom'del';constpaths={ styles{ src'src/styles/**/*.less', dest'assets/styles/'}, scripts{ src'src/scripts/**/*.js', dest'assets/scripts/'}};exportconstclean=()=>del('assets');exportfunctionstyles(){returngulp.src(paths.styles.src).pipe(less()).pipe(cleanCSS()).pipe(rename({ basename'main', suffix'.min'})).pipe(gulp.dest(paths.styles.dest));}exportfunctionscripts(){returngulp.src(paths.scripts.src,{ sourcemapstrue}).pipe(babel()).pipe(uglify()).pipe(concat('main.min.js')).pipe(gulp.dest(paths.scripts.dest));}functionwatchFiles(){gulp.watch(paths.scripts.src, scripts);gulp.watch(paths.styles.src, styles);}export{watchFilesaswatch};constclean=gulp.series(clean,gulp.parallel(styles, scripts));gulp.task('clean', clean);exportdefaultbuild;
What’s new in 4.0?!
- The task system was rewritten from the ground-up, allowing task composition using and methods
- The watcher was updated, now using chokidar (no more need for gulp-watch!), with feature parity to our task system
- First-class support was added for incremental builds using
- A method was exposed to create symlinks instead of copying files
- Built-in support for sourcemaps was added — the gulp-sourcemaps plugin is no longer necessary!
- Task registration of exported functions — using node or ES exports — is now recommended
- Custom registries were designed, allowing for shared tasks or augmented functionality
- Stream implementations were improved, allowing for better conditional and phased builds
Incremental Builds
You can filter out unchanged files between runs of a task using
the function’s option and :
constpaths={... images{ src'src/images/**/*.{jpg,jpeg,png}', dest'build/img/'}}functionimages(){returngulp.src(paths.images.src,{sincegulp.lastRun(images)}).pipe(imagemin({optimizationLevel5})).pipe(gulp.dest(paths.images.dest));}functionwatch(){gulp.watch(paths.images.src, images);}
Task run times are saved in memory and are lost when gulp exits. It will only
save time during the task when running the task
for a second time.
If you want to compare modification time between files instead, we recommend these plugins:
functionimages(){var dest ='build/img';returngulp.src(paths.images).pipe(newer(dest)).pipe(imagemin({optimizationLevel5})).pipe(gulp.dest(dest));}
If you can’t simply filter out unchanged files, but need them in a later phase
of the stream, we recommend these plugins:
functionscripts(){returngulp.src(scriptsGlob).pipe(cache('scripts')).pipe(header('(function () {')).pipe(footer('})();')).pipe(remember('scripts')).pipe(concat('app.js')).pipe(gulp.dest('public/'))}
Usage
Note: These examples assume you’re using Gulp 4. For examples that work with Gulp 3, check the docs for an earlier version of .
runs inside of Gulp tasks. No matter what else you do with , you must first import it into your gulpfile, making sure to pass it the compiler of your choice. From there, create a Gulp task that calls either (to asynchronously render your CSS), or (to render it synchronously). Then, export your task with the keyword. We’ll show some examples of how to do that.
️ Note: With Dart Sass, synchronous rendering is twice as fast as asynchronous rendering. The Sass team is exploring ways to improve asynchronous rendering with Dart Sass, but for now you will get the best performance from
Render your CSS
To render your CSS with a build task, then watch your files for changes, you might write something like this.:
'use strict'; var gulp = require('gulp'); var sass = require('gulp-sass')(require('sass')); function buildStyles() { return gulp.src('./sass/**/*.scss') .pipe(sass().on('error', sass.logError)) .pipe(gulp.dest('./css')); }; exports.buildStyles = buildStyles; exports.watch = function () { gulp.watch('./sass/**/*.scss', 'sass'); };
With synchronous rendering, that Gulp task looks like this:
function buildStyles() { return gulp.src('./sass/**/*.scss') .pipe(sass.sync().on('error', sass.logError)) .pipe(gulp.dest('./css')); };
Render with options
To change the final output of your CSS, you can pass an options object to your renderer. supports , with two unsupported exceptions:
- The option, which is used by internally.
- The option, which has undefined behavior that may change without notice.
For example, to compress your CSS, you can call . In the context of a Gulp task, that looks like this:
function buildStyles() { return gulp.src('./sass/**/*.scss') .pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError)) .pipe(gulp.dest('./css')); }; exports.buildStyles = buildStyles;
Or this for synchronous rendering:
function buildStyles() { return gulp.src('./sass/**/*.scss') .pipe(sass.sync({outputStyle: 'compressed'}).on('error', sass.logError)) .pipe(gulp.dest('./css')); }; exports.buildStyles = buildStyles;
Include a source map
can be used in tandem with to generate source maps for the Sass-to-CSS compilation. You will need to initialize before running , and write the source maps after.
var sourcemaps = require('gulp-sourcemaps'); function buildStyles() { return gulp.src('./sass/**/*.scss') .pipe(sourcemaps.init()) .pipe(sass().on('error', sass.logError)) .pipe(sourcemaps.write()) .pipe(gulp.dest('./css')); } exports.buildStyles = buildStyles;
By default, writes the source maps inline, in the compiled CSS files. To write them to a separate file, specify a path relative to the destination in the function.
var sourcemaps = require('gulp-sourcemaps'); function buildStyles() { return gulp.src('./sass/**/*.scss') .pipe(sourcemaps.init()) .pipe(sass().on('error', sass.logError)) .pipe(sourcemaps.write('./maps')) .pipe(gulp.dest('./css')); }; exports.buildStyles = buildStyles;
Configuration
Here’s a sample configuration for gulp-setup that sets the options for the existing default task, and creates a new gulp task called by extending the base one. You can override any of the default task parameters when extending a task.
The object key defines the name of the gulp task.
constpackages=require('gulp-setup/package.json');constgulp=require('gulp');const$=require('gulp-load-plugins')({ config packages });constsetup=require('gulp-setup')($, gulp,{ paths{ src'path/to/src', build'path/to/build', dist'path/to/dist'}, cachetrue, debugtrue, tasks{'javascript'{ options{ bundler'webpack'}},'javascript-ext'{ extends'javascript', paths{ src'path/to/custom-src'}}}});
Use latest JavaScript version in your gulpfile
Most new versions of node support most features that Babel provides, except the / syntax. When only that syntax is desired, rename to , install the module, and skip the Babel portion below.
Node already supports a lot of ES2015+ features, but to avoid compatibility problems we suggest to install Babel and rename your to .
npm install --save-dev @babel/register @babel/core @babel/preset-env
Then create a .babelrc file with the preset configuration.
{"presets""@babel/preset-env"}
And here’s the same sample from above written in ES2015+.
importgulpfrom'gulp';importlessfrom'gulp-less';importbabelfrom'gulp-babel';importconcatfrom'gulp-concat';importuglifyfrom'gulp-uglify';importrenamefrom'gulp-rename';importcleanCSSfrom'gulp-clean-css';importdelfrom'del';constpaths={ styles{ src'src/styles/**/*.less', dest'assets/styles/'}, scripts{ src'src/scripts/**/*.js', dest'assets/scripts/'}};exportconstclean=()=>del('assets');exportfunctionstyles(){returngulp.src(paths.styles.src).pipe(less()).pipe(cleanCSS()).pipe(rename({ basename'main', suffix'.min'})).pipe(gulp.dest(paths.styles.dest));}exportfunctionscripts(){returngulp.src(paths.scripts.src,{ sourcemapstrue}).pipe(babel()).pipe(uglify()).pipe(concat('main.min.js')).pipe(gulp.dest(paths.scripts.dest));}functionwatchFiles(){gulp.watch(paths.scripts.src, scripts);gulp.watch(paths.styles.src, styles);}export{watchFilesaswatch};constbuild=gulp.series(clean,gulp.parallel(styles, scripts));exportdefaultbuild;
gulp-watch
gulp-watch это название плагина для Gulp, который отслеживает изменение файлов. Начиная с четвёртой
версии Gulp gulp-watch включен в основной пакет и не требует отдельной установки.
Начнём с простого — делаем функцию, которая при каждом изменении файла index.html в
папке app будет выводить предупреждение.
Как это выглядит в Gulp 4
Чтобы запустить мониторинг пишем
gulp watch
Using gulpfile ~\Desktop\Sites\heihei\gulpfile.js
Starting ‘watch’…
Теперь вносим изменения в файл index.html и сохраняем
Starting ‘html’…
Кто-то отредактировал index.html!
Как это выглядело в Gulp 3
Создадим папку /app/assets/styles/ , в которой будут файлы .css для разработки
Напишем функцию, которая будет собирать все файлы .css из этой папки,
обрабатывать их с помощью sass и соединять в один файл /app/temp/styles/style.css
Мы уже писали такую функцию выше, просто немного изменим её.
Добавим мониторинг файлов CSS gulp.watch( «./app/assets/styles/**/*.css», style);
Теперь как только мы отредактируем один из файлов стилей watch заметит это изменение,
пропустит его через sass, соберет все файлы в один.
Зачем нужен SASS:
чтобы пользоваться css переменными. Создать переменную, которую потом
вставлять в .css пропускать через sass compiler и когда вдруг везде нужно будет
изменить значение этой переменной, например, на сайте изменится основной цвет, всё
что нам нужно будет сделать — это поменять одну переменную в одном файле.
чтобы делать вложения в стилях (nested css)
чтобы использовать mixins