Волшебная сборка проекта на WordPress при помощи пакетных менеджеров и напильника

c3877c68c8e547a4a20edd2205eab8d8.jpg

Сегодня я хочу поделиться с достопочтенной аудиторией Хабра своим подходом к организации автоматической сборки проекта на WordPress, который значительно экономит время при создании новых сайтов.

Предпосылки


И так, вы делаете сайты на WordPress, и с каждым новым проектом вам приходится идти на wordpress.org, качать от туда, собственно, сам WordPress + набор плагинов, которые вы используете постоянно. Или же установкой плагинов вы занимаетесь прямо из админ-панели или того хуже — копируете их из директории предыдущего сайта. Мне это всегда не нравилось, как-то не элегантно что ли, не удовлетворяет эстетическим потребностям. К тому же занимает хоть немного, но все же время. Поэтому я задумался, как бы этот процесс улучшить. Скачал все что нужно, сложил аккуратненько в папочку и выполнил «git init» и «git push». Что ж, теперь у меня есть репозиторий на Bitbucket, где хранится моя сборка WP со всем необходимым. С этого момента в начале процесса разработки можно выполнить «git clone» и получить нечто готовое к работе. Способ радовал меня не долго — обнаружились «недостатки». А именно:
  • избыточное использование репозитория (хранятся все иcходники плагинов и самой CMS);
  • всегда хранится старая версия всего (можно конечно периодически обновлять, но лень);
  • хочется хранить в том же репозитории исходники SCSS/SASS/LESS, не минифицированный JS-код и прочие важные компоненты, которые по идее не должны пересекаться с production-версией проекта;

Тут я и моя лень посовещались и пришли к выводу, что при начале работы над новым сайтом мы готовы тратить энергии не более чем на ввод одной (максимум двух) консольных команд для организации всего и вся и переходу непосредственно к процессу разработки. Потом лень отдельно от меня подумала и продолжила: «и что бы в Git все хранилось сразу, и что бы не надо было новые версии накатывать (изначально мол новые должны быть), и что бы можно было на сервере pull корректно выполнять (тебе ж потом это обслуживать все), и что бы вообще все само работало, и приступай побыстрее, а я пока отдохну».

Удовлетворяем хотелки лени


Первоначально я формализовал задачи в небольшой список:
  1. автоматизировать установку ядра WordPress и актуальных версий плагинов кочующих из проекта в проект;
  2. реализовать зависимость настроек проекта от серверного окружения;
  3. отделить исходники клиентской части от проекта;
  4. автоматизировать сборку клиентской части;
  5. организовать не избыточное хранение в Git-репозитории.

И приступил к реализации. Для начала я отправился читать документацию WP и нашел там прекрасную вещь, которая позволяет отделить ядро CMS от того, что изменяет разработчик. Набросал по этому случаю следующую структуру проекта:

content/
wp/
index.php
wp-config.php

В директории «wp» хранятся файлы ядра WordPress, «content» — папка для тем, плагинов, языковых версий и т.д., «wp-config.php» — стандартный файл настроек WP, а в «index.php», руководствуясь документацией я поместил следующее:
define('WP_USE_THEMES', true);
require( dirname( __FILE__ ) . '/wp/wp-blog-header.php' );

Запустил на сервере, проверил, ок, работает. Теперь нужно сделать так, что бы скачивалась самая последняя версия WP. Для этого я использовал Composer (как его установить, можно почитать тут). Все файлы, которые я создал ранее я поместил в папку «app», для того, что бы вынести все служебные файлы на уровень выше от исполняемого «index.php». В дальнейшем мой сайт будет запускаться из этой директории (не забудьте поправить настройки хоста для вашего сервера). А папка «wp» была вычищена от всего содержимого. В корень проекта я поместил файл «composer.json» со следующим содержимым:
{
  "require": {
    "php": ">=5.4",
    "johnpbloch/wordpress": "*",
  },
  "extra": {
    "wordpress-install-dir": "app/wp",
  }
}

«johnpbloch/wordpress» — форк WP, пригодный для установки через Composer, а «wordpress-install-dir» указывает на директорию установки ядра CMS. Написав в консоли:
composer install

я убедился, что все работает. Свежий WordPress скачался в «app/wp». Что же с плагинами? С ними все хорошо, благодаря проекту wpackagist.org их так же можно подтягивать через Composer. Для этого нужно лишь немного модифицировать «composer.json»:
{
  "repositories":[
    {
      "type":"composer",
      "url":"https://wpackagist.org"
    }
  ],
  "require": {
    "php": ">=5.4",
    "johnpbloch/wordpress": "*",
    "wpackagist-plugin/rus-to-lat-advanced": "*",
    "wpackagist-plugin/advanced-custom-fields": "*",
    "wpackagist-plugin/all-in-one-seo-pack": "*",
    "wpackagist-plugin/google-sitemap-generator": "*",
    "wpackagist-plugin/contact-form-7": "*",
    "wpackagist-plugin/woocommerce": "*",
    "wpackagist-plugin/saphali-woocommerce-lite": "*"
  },
  "extra": {
    "wordpress-install-dir": "app/wp",
    "installer-paths": {
      "app/content/plugins/{$name}/": ["vendor:wpackagist-plugin"],
      "app/content/themes/{$name}/": ["vendor:wpackagist-theme"]
    }
  }
}

В секции «repositories» указывается адрес «wpackagist», в секции «installer-paths» указываются пути, куда будут устанавливаться плагины и темы, а в секции «require» добавляются названия WP-плагинов в виде «wpackagist-plugin/{{plugin_name}}». В «wpackagist» доступны почти все плагины с wordpress.org, доступность плагинов можно смотреть в поиске на сайте wpackagist.org.

Выполнив:

composer update

увидел, как в директории «app/content/plugins» появились все нужные плагины. Теперь нужно разобраться с настройками, напомню, что стоит задача сделать настройки БД и дебага зависимыми от среды разработки, на локальном сервере свои, на боевом свои. Для этого выдавим их в отдельный файл «local-config.php»:
define( 'DB_NAME', '%%DB_NAME%%' );
define( 'DB_USER', '%%DB_USER%%' );
define( 'DB_PASSWORD', '%%DB_PASSWORD%%' );
define( 'DB_HOST', '%%DB_HOST%%' ); // Probably 'localhost'

ini_set( 'display_errors', true );
define( 'WP_DEBUG_DISPLAY', true );

define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
define( 'NONCE_KEY',        'put your unique phrase here' );
define( 'AUTH_SALT',        'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
define( 'NONCE_SALT',       'put your unique phrase here' );

и изменим «wp-config.php» следующим образом:
if ( file_exists( dirname( __FILE__ ) . '/local-config.php' ) ) {
	define( 'WP_LOCAL_DEV', true );
	include( dirname( __FILE__ ) . '/local-config.php' );
} else {
	define( 'WP_LOCAL_DEV', false );
	define( 'DB_NAME', '%%DB_NAME%%' );
	define( 'DB_USER', '%%DB_USER%%' );
	define( 'DB_PASSWORD', '%%DB_PASSWORD%%' );
	define( 'DB_HOST', '%%DB_HOST%%' ); // Probably 'localhost'

	ini_set( 'display_errors', 0 );
	define( 'WP_DEBUG_DISPLAY', false );

	define( 'AUTH_KEY',         'put your unique phrase here' );
	define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
	define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
	define( 'NONCE_KEY',        'put your unique phrase here' );
	define( 'AUTH_SALT',        'put your unique phrase here' );
	define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
	define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
	define( 'NONCE_SALT',       'put your unique phrase here' );
}

Теперь, если существует файл «local-config.php», настройки будут подхватываться из него. Этот файл нужно добавить в ».gitignor» (зачем нам пароли от БД в репозитории?). Самое время внести данные для доступа к базе данных в «local-config.php», запустить процедуру установки WordPress и посетить админку.

В админке нужно посетить раздел «Настройки → Общие» и там поправить адреса, следующим образом:

66bc648e71d64a998e2112df11816e52.png

Адрес WordPress c »/wp» на конце, адрес сайта без »/wp».

Здорово, сайтом можно пользоваться. Следующим этап я посвятил пользовательским стилям и скриптам (а то как-то не логично, на сервере все само собирается, а всякие jquery вручную качать?). В качестве подготовки я отредактировал структуру проекта:

app/
       content/
             theme/
                  mytheme/
                        build/
                        index.php
                        style.css
       wp/
       index.php
       local-config.php
       wp-config.php
src/
      fonts/
      js/
            main.js
      scss/
            style.ccss 
composer.json

В папке «src/» хранятся исходные файлы шрифтов, скриптов и стилей. Далее они собираются с помощью gulp, минифицируются и складываются в папку «app/content/theme/mytheme/build». В качестве препроцессора для CSS я использую SCSS (как установить, думаю всем известно, но если нет, то вот инструкция), для сборки JS — browserify. Посчитал логичным, что зависимости клиентской части нужно подтягивать при помощи nmp. Файл «package.json» у меня получился такой:

{
  "devDependencies": {
    "bourbon": "*",
    "bourbon-neat": "*",
    "browserify": "*",
    "fullpage.js": "*",
    "gulp": "*",
    "gulp-clean-css": "*",
    "gulp-concat": "*",
    "gulp-sass": "*",
    "gulp-sourcemaps": "*",
    "gulp-uglify": "*",
    "jquery": "*",
    "normalize-scss": "*",
    "vinyl-source-stream": "*"
  }
}

Секции кроме «devDependencies», заполнять не стал, поскольку публиковать это в npm я явно не планирую. Пишу в консоли:
npm install

Жду пару минут и вижу, что все указанные зависимости аккуратно оказались в «node_modules». Вишенкой на торте послужил файл «gulpfile.js» с таким содержимым:
'use strict';

var browserify = require('browserify'),
    source = require('vinyl-source-stream'),
    gulp = require('gulp'),
    sass = require('gulp-sass'),
    uglify = require('gulp-uglify'),
    cleanCSS = require('gulp-clean-css'),
    sourcemaps = require('gulp-sourcemaps'),
    sourcePath = './src/',
    buildPath = './app/content/themes/mytheme/build/';

//scss
gulp.task('scss', function () {
    return gulp.src('./src/scss/style.scss')
        .pipe(sass().on('error', sass.logError))
        .pipe(gulp.dest(buildPath + 'css'));
});

gulp.task('scss:watch', function () {
    return gulp.watch(sourcePath + 'scss/**/*.scss', ['scss']);
});

//js
gulp.task('browserify', function() {
    return browserify(sourcePath + 'js/main.js')
        .bundle()
        .pipe(source('main.js'))
        .pipe(gulp.dest(buildPath + 'js'));
});

gulp.task('browserify:watch', function () {
    return gulp.watch(sourcePath + 'js/**/*.js', ['browserify']);
});

//fonts
gulp.task('copy:fonts', function () {
    gulp.src(sourcePath + 'fonts/**/*', {base: sourcePath + 'fonts'})
        .pipe(gulp.dest(buildPath + 'fonts'));
});

//minify
gulp.task('minify:js', ['browserify'], function(){
    return gulp.src(buildPath + 'js/*.js')
        .pipe(sourcemaps.init())
        .pipe(uglify())
        .pipe(sourcemaps.write())
        .pipe(gulp.dest(buildPath + 'js'))
});

gulp.task('minify:css', ['scss'], function(){
    return gulp.src(buildPath + 'css/*.css')
        .pipe(cleanCSS({compatibility: 'ie9'}))
        .pipe(gulp.dest(buildPath + 'css'));
});


//task groups
gulp.task('default', ['copy:fonts', 'scss', 'browserify']);
gulp.task('watch', ['copy:fonts', 'scss:watch', 'browserify:watch']);
gulp.task('production', ['copy:fonts', 'scss', 'browserify', 'minify:js', 'minify:css']);

Команда «gulp» скопирует шрифты, скомпилирует SCSS, склеит JS и сложит это все аккуратненько в папку билда. «gulp watch» делает тоже самое, но при каждом изменении файла. «gulp production» дополнительно почистит файлы от комментариев и минифицирует.

Что в итоге?


В итоге вышеописанное вам повторять совсем не обязательно. Я все удобненько залил на GitHub: https://github.com/IvanZhuck/kosher_wp_seeder.

Для запуска необходимо клонировать репозиторий и выполнить следующие команды (предварительно поправив список плагинов и зависимостей, если это требуется):

composer install
npm install

Я и моя лень довольны, проекты стали стартовать быстрее, а работа приятнее. Ваши вопросы и предложения жду в комментариях.

Комментарии (0)

© Habrahabr.ru