Ответы пользователя по тегу Gulp.js
  • Include HTML с условиями?

    delphinpro
    @delphinpro Куратор тега HTML
    frontend developer
    Используйте полноценные шаблонизаторы, а не всякие суррогаты.
    Например twig (gulp-twig для верстки)

    {% if some_variable == 2 %}
      {% include "file1.twig" %}
    {% else %}
      {% include "file2.twig" %}
    {% endif %}


    UPD
    Почитал комменты. Twig это что называется like html шаблонизатор. Т.е. обычный html файл скормленный шаблонизатору не вызовет ошибок компиляции. Это значит, что вы можете по сути в свой html просто вставлять управляющие конструкции шаблонизатора.
    Ответ написан
    6 комментариев
  • Не могу найти нормальные шаблоны для адаптивной верстки (gulp + sass + browser-sync)?

    delphinpro
    @delphinpro Куратор тега Sass
    frontend developer
    Вот простой конфиг

    package.json
    {
      "name": "mysite.local",
      "version": "1.0.0",
      "description": "",
      "main": "gulpfile.js",
      "dependencies": {
        "bs-grid-system": "^2.0.3",
        "jquery": "^3.3.1",
        "normalize.css": "^8.0.1",
        "tiny-slider": "^2.9.0",
        "whatwg-fetch": "^3.0.0"
      },
      "devDependencies": {
        "@babel/core": "^7.2.0",
        "@babel/preset-env": "^7.2.0",
        "browser-sync": "^2.26.3",
        "gulp": "^3.9.1",
        "gulp-autoprefixer": "^6.0.0",
        "gulp-babel": "^8.0.0",
        "gulp-changed-in-place": "^2.3.0",
        "gulp-concat": "^2.6.1",
        "gulp-plumber": "^1.2.1",
        "gulp-sass": "^4.0.2",
        "gulp-sequence": "^1.0.0",
        "gulp-sourcemaps": "^2.6.4",
        "gulp-twig": "^1.2.0"
      },
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "delphinpro <delphinpro@yandex.ru>",
      "license": "MIT"
    }
    gulpfile.js
    const gulp = require('gulp');
    const sass = require('gulp-sass');
    const twig = require('gulp-twig');
    const babel = require('gulp-babel');
    const concat = require('gulp-concat');
    const plumber = require('gulp-plumber');
    const sequence = require('gulp-sequence');
    const sourcemaps = require('gulp-sourcemaps');
    const autoprefixer = require('gulp-autoprefixer');
    const changed = require('gulp-changed-in-place');
    const bs = require('browser-sync').create();
    
    gulp.task('sass', function () {
        return gulp.src([
            './node_modules/normalize.css/normalize.css',
            './node_modules/tiny-slider/dist/tiny-slider.css',
            './src/sass/**/*.scss',
        ])
            .pipe(plumber())
            .pipe(sourcemaps.init())
            .pipe(sass({ outputStyle: 'nested' }))
            .pipe(autoprefixer())
            .pipe(concat('main.css'))
            .pipe(sourcemaps.write('.'))
            .pipe(gulp.dest('./public_html/design/'))
            .pipe(bs.stream())
            ;
    });
    
    gulp.task('js:vendor', function (done) {
        gulp.src([
            './node_modules/jquery/dist/jquery.min.js',
            './node_modules/whatwg-fetch/dist/fetch.umd.js',
            './node_modules/tiny-slider/dist/min/tiny-slider.js',
        ])
            .pipe(plumber())
            .pipe(sourcemaps.init({ loadMaps: true }))
            .pipe(concat('vendor.js'))
            .pipe(sourcemaps.write('.'))
            .pipe(gulp.dest('./public_html/design/'))
            .on('end', done)
        ;
    });
    
    gulp.task('js', function (done) {
        gulp.src([
            './src/js/main.js',
            './src/js/**/*.js',
        ])
            .pipe(plumber())
            .pipe(sourcemaps.init())
            .pipe(babel())
            .pipe(concat('main.js'))
            .pipe(sourcemaps.write('.'))
            .pipe(gulp.dest('./public_html/design/'))
            .on('end', function () {
                bs.reload();
                done();
            })
        ;
    });
    
    gulp.task('twig', function (done) {
        gulp.src([
            './src/twig/*.twig',
        ])
            .pipe(plumber())
            .pipe(twig({
                base: [__dirname],
            }))
            .pipe(changed({ firstPass: true }))
            .pipe(gulp.dest('./public_html/'))
            .on('end', function () {
                bs.reload();
                done();
            })
        ;
    });
    
    gulp.task('serve', function () {
        bs.init({
            ui: false,
            //proxy: 'mysite.local',
            server : './public_html',
            browser: ['chrome'],
        });
    
        //    gulp.watch('./public_html/*.html').on('change', bs.reload);
        gulp.watch('./src/sass/**/*.scss', ['sass']);
        gulp.watch('./src/js/**/*.js', ['js']);
        gulp.watch('./src/twig/**/*.twig', ['twig']);
    });
    
    gulp.task('default', sequence(['twig', 'sass', 'js', 'js:vendor'], 'serve'));
    Структура каталогов
    5cb718165250b202742020.png
    Ответ написан
    Комментировать
  • Можно ли отобразить структуру *.html при запуске Gulp + BrowserSync?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    не называйте свои файлы index.html (пусть будет homepage.html), и браузер синк в корне отобразит вам красивый список файлов-страниц.
    Ответ написан
    6 комментариев
  • Как сделать асинхронное выполнение в gulp?

    delphinpro
    @delphinpro Куратор тега Gulp.js
    frontend developer
    Что еще за return glob() ?

    Все очень просто — в done вызывайте коллбэк завершения таска

    Как-то так

    bootprintService
     …
     .done(function(){ cb() });


    Однако, учитывая, что эта хрень вызывается в цикле, следйет каждый вызов обернуть в промис, в done резолвить промис,

    let services = [];
    items.forEach((item) => {
      services.push(new Promise((resolve, reject)=>{
        bootprintService
        ...
        .done(() => resolve());
      }))
    });


    а коллбэк вызывать в конце, после разрешения всех промисов

    Promise.all(services)
    .then(function(){  cb() })
    Ответ написан
    1 комментарий
  • Gulp 4 и BrowserSync reload?

    delphinpro
    @delphinpro Куратор тега Gulp.js
    frontend developer
    Вы документацию-то гляньте. Там есть готовый пример
    https://browsersync.io/docs/gulp#gulp-sass-css
    Ответ написан
  • Как автоматически создавать пустые файлы внутри созданной папки?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    Всё верно, написать отдельный таск для галпа или скрипт для запуска через npm run

    Скрипт простой: создать папку, создать файлы.
    Полная документация по работе с файловой системой https://nodejs.org/api/fs.html
    И небольшой конспект на хабре https://habr.com/ru/company/ruvds/blog/424969/ (этого должно хватить)
    Ответ написан
  • Как правильно собрать спрайты svg в gulp?

    delphinpro
    @delphinpro Куратор тега Gulp.js
    frontend developer
    Многоцветные, как правило, не нуждаются в изменении цветов через css. Но иногда бывает.

    Я в своих иконках использую только заливку (без обводки). Это немного упрощает управление.
    Удаляю атрибуты заливки только черным цветом
    $('[fill="#000"]').removeAttr('fill');
    $('[fill="#000000"]').removeAttr('fill');

    Черный - это дефолтный цвет и он не нужен, только мешает переопределению в css.
    Всё, что не черное — цветное, и попадает в спрайт как есть.
    Базовый стиль для заливки иконок
    fill: currentColor
    думаю, понимаете, в чем сила.

    Особые иконки, в том числе многоцветные, требующие нестандартного поведения или управления цветом, правятся вручную — элементы группируются и им назначаются отдельные классы, с помощью которых происходит переопределение свойств в css.
    Ответ написан
    3 комментария
  • Как вставить код css из файла в шаблон Twig?

    delphinpro
    @delphinpro Куратор тега Gulp.js
    frontend developer
    Напишите функцию для твига. Она будет просто читать и возвращать содержимое файла.

    В принципе, то же самое делает штатная source(), вы просто неверный путь ей передаёте.
    В настройки вызова twig() передайте опцию base: 'src/twig_tpl' (ну это путь к шаблонам) и потом указывайте пути в шаблонах от этой папки
    Ответ написан
    Комментировать
  • Как сохранить dependencies npm пакеты в другую папку и подцепить главные файлы?

    delphinpro
    @delphinpro Куратор тега Gulp.js
    frontend developer
    Как, как.. Джаваскриптом об косяк =)))

    Нужно скопировать файлы? Не вопрос! Напишем задачу копирования.

    global.ROOT = 'корень проекта';
    let config = {
      root: {
        build: 'dist'
      }
    };
    
    config.copy = [
        { src: 'source/assets/**', dest: '/'},
        { src: 'source/assets/.htaccess', dest: '/'},
        { src: 'node_modules/tiny-slider/dist/tiny-slider.js', dest: '/design/js' },
        { src: 'node_modules/tiny-slider/dist/tiny-slider.css', dest: '/design/css' },
        { src: 'node_modules/cool-menu/dist/cool-menu.js', dest: '/design/js' },
        { src: 'node_modules/svg4everybody/dist/svg4everybody.js', dest: '/design/js' },
        { src: 'node_modules/vanilla-text-mask/dist/vanillaTextMask.js', dest: '/design/js' },
        { src: 'node_modules/tippy.js/dist/tippy.all.min.js', dest: '/design/js' },
    ];
    
    function copyFiles(conf, options) {
        return new Promise((resolve, reject) => {
    
            if (!('src' in conf)) reject('Invalid config for "copy" task: undefined "src" param');
            if (!('dest' in conf)) conf.dest = '';
            if ('extensions' in conf) { }
    
            let source = path.join(global.ROOT, conf.src);
            let dest   = path.join(global.ROOT, options.root.build, conf.dest);
    
            let pipeline = gulp.src(source).pipe(gulp.dest(dest));
    
            pipeline.on('error', function (err) {
                reject(err);
            });
    
            pipeline.on('end', function () {
                resolve();
            });
    
    	});
    }
    
    gulp.task('copy', function(done){
    	
    	let copies = [];
    
    	options.copy.forEach(item => {
    		copies.push(copyFiles(item, options));
    	});
    
    	Promise.all(copies).then(value => done(), reason => done());
    	
    });
    Ответ написан
  • Почему после сборки проекта не появляется папка dist в Gulp 4?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    в общем проблема похоже в методе task()
    Его сигнатура изменилась
    task([taskName], taskFunction)

    Здесь нет третьего параметра, как было в третьей версии.
    Соответственно объявленные анонимные функции не запускаются (этот параметр игнорится)

    Старый подход к объявлению задач с предварительным запуском других не работает.
    Нужно отдельно описывать все задачи и запускать через series/parallel, или анонимными функциями в том же series

    Было:

    gulp.task(
      'sometask',      // название задачи
      ['anothertask'], // выполнить перед задачей
      function(){}     // сама задача
    )


    Стало:

    gulp.task(
      'sometask',     // название задачи
      gulp.series(    // последовательно выполнить
        'anothertask',  // другие задачи
         function(){}   // и саму задачу
      )
    )


    Добавлю неправильный вариант, который может ввести в заблуждение:

    gulp.task(
      'sometask',     // название задачи
      gulp.series('anothertask'),  // выполнить другие задачи
      function(){}   // и саму задачу
    )
    Ответ написан
    8 комментариев
  • Почему не запускается таск «clean» во время сборки?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    просто вызовите коллбек, сообщив этим, что задача завершена.

    gulp.task('build', gulp.parallel('clean', 'nunjucks', 'sass', 'scripts', 'css-libs', 'img'), function(cb) {
      var buildHtml = gulp.src('app/*.html')
      .pipe(gulp.dest('dist'))
      .on('end', function(){
        cb();// сигналим о завершении
      })


    gulp.task('clean', function(cb) {
      del('dist').then( (paths) => {
        cb(); // сигналим о завершении
      }); 
    });


    Очистку не нужно запускать параллельно с другими задачами. Сначала очистить, потом создавать. т.е.

    gulp.series(
      'clean',
       gulp.parallel(все остальное)
    )
    Ответ написан
  • Как решить проблему с отрицательными значениями viewBox у svg?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    Я всегда svg иконки предварительно подготавливаю в люстре — привожу к единому размеру (viewBox), обычно 128 или 256 и выравниваю иконку внутри области, а также по дробным пикселям. Потом сохраняю в svg, которые прекрасно и без глюков хаваются галпом.
    Ответ написан
    Комментировать
  • Как менять $primary в 4-ом бутстрапе в зависимости от id страницы?

    delphinpro
    @delphinpro Куратор тега Sass
    frontend developer
    Делаете несколько файлов: main-default.scss, main-red.scss и т.п.

    В каждом пишете примерно следующее

    $primary: red;
    @import 'vars.scss';
    …


    Дальше дело техники — на каждой странице подключаете свой файл.

    Очевидный недостаток — слишком много дублирующихся стилей на выходе. Но с другой стороны подключается только один из main файлов, и это самое простое решение, не требующее вмешательства в исходники бутстрапа.

    Другой вариант — выдрать все стили, влияющие на цветовую схему и подключать main.css + цветовую схему. Тут возможны под-варианты — отдельные файлы для тем, один файл через корневой селектор. В любом случае тут уже придется вмешиваться в исходники или дублировать часть исходников в своих темах.

    Если у вас будет не очень много тем, лучше пойти по первому пути. Если количество цветовых решений не ограничено, то вытащить часть стилей и инлайнить их прямо в страницу (готовым css).
    Ответ написан
  • Как в одном запросе gulp переместить сразу два файла, по разным папкам?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    Создавайте одну задачу, внутри нее два раза вызывайте галп.
    Можно прямо так и оставить.
    Если нужно сигналить об окончании задачи, то оберните вызовы в промисы, и воспользуйтесь методом Promise.all для получения сигнала об окончании всех (в данном случае двух) процессов.

    gulp.task('mytask', function(done){
      let pipes = [];
      pipes.push(new Promise((resolve, reject) => {
        gulp.src(...)
          .pipe()
           …  
          .on('error', (err) => reject(err))
          .on('end', () => resolve())
      }));
      //... повторить нужное кол-во раз
    
      Promise.all(pipes).then((ok) => done(), (err) => done())
    })
    Ответ написан
    Комментировать
  • Без обновления страницы не запускается сайт с сервера - browser-sync, как исправить?

    delphinpro
    @delphinpro Куратор тега Gulp.js
    frontend developer
    У вас все задачи запускаются параллельно. Сервер и вотчер лучше запускать после завершения остальных тасков.

    Если у вас третий галп, воспользуйтесь пакетом gulp-sequence для очередного запуска задач. В четверке есть встроенные средства.
    Ответ написан
  • Почему при вводе кириллицы в код, gulp прекращает работу?

    delphinpro
    @delphinpro Куратор тега Gulp.js
    frontend developer
    Используйте gulp-plumber

    var plumber = require('gulp-plumber'); //+
    
    gulp.task('js:build', function () {
      gulp.src(path.src.js)
        .pipe(plumber()) // +
        .pipe(rigger())
        .pipe(gulp.dest(path.build.js))
        .pipe(reload({
          stream: true
        }));
    });
    Ответ написан
  • Почему не завершается процесс gulp?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    В любой непонятной ситуации читай документацию! =)

    Кто вас научил так писать код? Абсолютно нечитаемо и непонятно сходу что там происходит. Любой код (особенно тот что вы показываете) должен быть аккуратным и красивым.

    gulp.task('sass', function() {
      return gulp.src(paths.src.sass)
                 .pipe(sassGlob())
                 .pipe(sourcemaps.init())
                 .pipe(sass(sassConfig))
                 .on('error', notify.onError(errorHandlerFunction))
                 .pipe(sourcemaps.write())
                 .pipe(gulp.dest(paths.dist.css))
                 .pipe(reload({stream: true}))
      ;
    });

    Согласитесь, что так намного понятнее.

    Теперь к вашему вопросу.
    Смотрим документацию, читаем и пишем:

    // Подключаем библу
    const browserSync = require('browser-sync').create(); // create!!!
    
    // Инициализируем сервер
    browserSync.init(settings);
    
    // для отслеживания изменений юзаем watch
    // который ЗАПУСКАЕТ ЗАДАЧУ, а не перезагружает страницу!!!
    gulp.watch(paths.watch.js).on('change', ['pug']);
    
    // А уже в самой задаче, по ее окончанию, вызываем перезагрузку страницы
    .pipe(browserSync.reload)
    
    // А стили можно инъектить вообще без перезагрузки страницы:
    .pipe(browserSync.stream())
    Ответ написан
  • Почему не удается запустить gulp сборку проекта на другом компьютере?

    delphinpro
    @delphinpro Куратор тега JavaScript
    frontend developer
    Local gulp not found in ~\Downloads\Папка

    Локальная установка галпа не найдена.
    npm install делали?
    хотя конечно же делали…
    Может быть проблема в кириллическом пути к проекту? Я со времен DOS/WIN98 не доверяю кириллице в файловой системе.
    Ответ написан
    4 комментария
  • Почему не срабатывает плагин gulp-changed?

    delphinpro
    @delphinpro Куратор тега Gulp.js
    frontend developer
    Используйте gulp-changed для бинарных файлов
    и gulp-changed-in-place для текстовых

    Ну и плагин нужно вставлять после сборки. Вы проверяете хеш еще не обработанного файла (без инклюдов), естественно он будет отличаться от обработанного.
    Ответ написан
    2 комментария
  • PostCSS - аналог breakpoints для postcss как в sass?

    delphinpro
    @delphinpro Куратор тега Sass
    frontend developer
    Зачем отказываться от привычных инструментов https://github.com/postcss/postcss-scss
    Ответ написан