Здесь мы переходим ко второй части руководства по настройке Gulp для оптимальной разработки WordPress.
Если вы пропустили первую часть, где мы установили все модули, необходимые для задач, которые нам понадобятся, «вы можете найти это здесь."

Напоминаю, что мы напишем наш конфигурационный файл gulpfile.babel.js на JavaScript ES6, как я объяснил в первой части этого руководства.

Импорт модулей

Теперь приступим к импорту загруженных модулей в наш файл gulpfile.babel.js.

import { src, dest, watch, parallel, series } from 'gulp';
import yargs from 'yargs';
import sass from 'gulp-sass';
import cleanCss from 'gulp-clean-css';
import gulpif from 'gulp-if';
import postcss from 'gulp-postcss';
import sourcemaps from 'gulp-sourcemaps';
import autoprefixer from 'autoprefixer';
import imagemin from 'gulp-imagemin';
import webpack from 'webpack-stream';
import del from 'del';
import browserSync from "browser-sync";

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

const PRODUCTION = yargs.argv.prod;

Стиль задачи

Напишем нашу первую задачу, которая будет использоваться для обработки нашего SCSS.

Задача ставится на обнаружение любых изменений в файлах SCSS в папке src, а также на компиляцию, добавление префиксов кросс-браузеров и минимизацию (в случае, если мы хотим создать сборку для производства) файл bundle.scss.

Если вам интересно, что именно делает server.stream(), он используется для прямого внедрения CSS на нашу страницу без перезагрузки. Это функция BrowserSync, мы увидим позже.

export const styles = () => {
    return src('src/scss/bundle.scss')
        .pipe(gulpif(!PRODUCTION, sourcemaps.init()))
        .pipe(sass().on('error', sass.logError))
        .pipe(gulpif(PRODUCTION, postcss([ autoprefixer ])))
        .pipe(gulpif(PRODUCTION, cleanCss({compatibility:'ie8'})))
        .pipe(gulpif(!PRODUCTION, sourcemaps.write()))
        .pipe(dest('dist/css'))
        .pipe(server.stream());
};

Изображения задач

Вторая задача, которую мы напишем, - это задача, необходимая для сжатия изображений.

export const images = () => {
    return src('src/images/**/*.{jpg,jpeg,png,svg,gif}')
        .pipe(gulpif(PRODUCTION, imagemin()))
        .pipe(dest('dist/images'));
};

Функции копирования и очистки

Нам также необходимо скопировать файл CSS, JS и изображения, обработанные в папку dist, которую мы будем загружать в WordPress.

Нам также пригодится функция, которая очищает папку dist каждый раз, когда мы начинаем разработку.

export const copy = () => {
    return src(['src/**/*','!src/{images,js,scss}','!src/{images,js,scss}/**/*'])
        .pipe(dest('dist'));
};

export const clean = () => del(['dist'])

Скрипты задач

Изображения и SCSS в порядке, теперь мы переходим к JavaScript.

export const scripts = () => {
    return src('src/js/bundle.js')
        .pipe(webpack({
            module: {
                rules: [
                    {
                        test: /\.js$/,
                        use: {
                            loader: 'babel-loader',
                            options: {
                                presets: []
                            }
                        }
                    }
                ]
            },
            mode: PRODUCTION ? 'production' : 'development',
            devtool: !PRODUCTION ? 'inline-source-map' : false,
            output: {
                filename: 'bundle.js'
            },
        }))
        .pipe(dest('dist/js'));
};

BrowserSync

Мы используем BrowserSync для автоматической перезагрузки страницы в случае изменения файла PHP или JS, в то время как мы используем server.stream(), который мы добавили в стиль задачи, для непосредственного внедрения CSS на страницу без необходимости перезагрузки.

Мы указываем сервер BrowserSync на нашем локальном сервере, указывая в proxy наш домен.

Как я объяснил в этом посте, я предлагаю вам использовать другой домен из .local, чтобы избежать проблем, связанных с замедлением при обновлении сервера BrowserSync, которое могло бы сорвать всю работу.

const server = browserSync.create();
export const serve = done => {
    server.init({
        proxy: "https://project.dev/" // your local website link
    });
    done();
};

export const reload = done => {
    server.reload();
    done();
};

Наблюдать за задачами

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

export const watchForChanges = () => {
    watch('src/scss/**/*.scss', series(styles));
    watch('src/images/**/*.{jpg,jpeg,png,svg,gif}', series(images, reload));
    watch(['src/**/*','!src/{images,js,scss}','!src/{images,js,scss}/**/*'], series(copy, reload));
    watch('src/js/**/*.js', series(scripts, reload));
    watch("**/*.php", reload);
};

Заключительный этап

Наконец, давайте добавим все наши задачи в build и dev задачи.

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

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

export const dev = series(clean, parallel(styles, images, copy, scripts), serve, watchForChanges);
export const build = series(clean, parallel(styles, images, copy, scripts));
export default dev;

Затем добавьте задачи в файл package.json, чтобы обе задачи были у вас под рукой.

"scripts": {
    "start": "gulp",
    "build": "gulp build --prod"
  },

Выводы

Наконец, вот файл gulpfile.babel.js целиком:

import { src, dest, watch, parallel, series } from 'gulp';
import yargs from 'yargs';
import sass from 'gulp-sass';
import cleanCss from 'gulp-clean-css';
import gulpif from 'gulp-if';
import postcss from 'gulp-postcss';
import sourcemaps from 'gulp-sourcemaps';
import autoprefixer from 'autoprefixer';
import imagemin from 'gulp-imagemin';
import webpack from 'webpack-stream';
import del from 'del';
import browserSync from "browser-sync";

const PRODUCTION = yargs.argv.prod;

export const styles = () => {
    return src('src/scss/bundle.scss')
        .pipe(gulpif(!PRODUCTION, sourcemaps.init()))
        .pipe(sass().on('error', sass.logError))
        .pipe(gulpif(PRODUCTION, postcss([ autoprefixer ])))
        .pipe(gulpif(PRODUCTION, cleanCss({compatibility:'ie8'})))
        .pipe(gulpif(!PRODUCTION, sourcemaps.write()))
        .pipe(dest('dist/css'))
        .pipe(server.stream());
};

export const images = () => {
    return src('src/images/**/*.{jpg,jpeg,png,svg,gif}')
        .pipe(gulpif(PRODUCTION, imagemin()))
        .pipe(dest('dist/images'));
};

export const copy = () => {
    return src(['src/**/*','!src/{images,js,scss}','!src/{images,js,scss}/**/*'])
        .pipe(dest('dist'));
};

export const clean = () => del(['dist']);

export const scripts = () => {
    return src('src/js/bundle.js')
        .pipe(webpack({
            module: {
                rules: [
                    {
                        test: /\.js$/,
                        use: {
                            loader: 'babel-loader',
                            options: {
                                presets: []
                            }
                        }
                    }
                ]
            },
            mode: PRODUCTION ? 'production' : 'development',
            devtool: !PRODUCTION ? 'inline-source-map' : false,
            output: {
                filename: 'bundle.js'
            },
        }))
        .pipe(dest('dist/js'));
};

const server = browserSync.create();
export const serve = done => {
    server.init({
        proxy: "https://project.dev/" // your local website link
    });
    done();
};
export const reload = done => {
    server.reload();
    done();
};

export const watchForChanges = () => {
    watch('src/scss/**/*.scss', series(styles));
    watch('src/images/**/*.{jpg,jpeg,png,svg,gif}', series(images, reload));
    watch(['src/**/*','!src/{images,js,scss}','!src/{images,js,scss}/**/*'], series(copy, reload));
    watch('src/js/**/*.js', series(scripts, reload));
    watch("**/*.php", reload);
};

export const dev = series(clean, parallel(styles, images, copy, scripts), serve, watchForChanges);
export const build = series(clean, parallel(styles, images, copy, scripts));
export default dev;

Все, что нам нужно сделать, это импортировать файлы bundle.js и bundle.css в WordPress, добавив функцию импорта в functions.php

function _yourtheme_assets() {
  wp_enqueue_style( '_yourtheme-stylesheet', get_template_directory_uri() . '/dist/css/bundle.css', array(), '1.0.0', 'all' );
  
  wp_enqueue_script( '_yourtheme-scripts', get_template_directory_uri() . '/dist/js/bundle.js', array(), '1.0.0', true );
}
add_action('wp_enqueue_scripts', '_yourtheme_assets');

Не забудьте отредактировать _yourtheme, указав имя вашей темы.

Вам просто нужно работать над своим новым проектом, отдавая npm run start из терминала на этапе разработки и npm run build для окончательной сборки, готовой к развертыванию.

Фото Franck V. на Unsplash

Первоначально опубликовано на https://dannyspina.com 4 сентября 2019 г.