ИНН 5260488533
+7 993 435 0226
Нижний Новгород, ул. Гоголя, 45а-13
info@sawtech.ru
Политика обработки персональных данных
PhpStorm деплоймент на несколько серверов

Бывает так, что один и тот же код нужно поддерживать на нескольких серверах, например плагин или тему. Можно пойти путем наименьшего сопротивления, и заливать каждый раз новую версию через FTP-менеджеры. Если сайтов 2-3, то вроде бы не проблема, но когда их копится пару десятков, то тут могут начаться сложности: «А сюда я уже заливал? Ой, забыл!» — и т.д. Меня этот путь не устраивал изначально, во-первых как-то не по-программистски, во-вторых вариант «Ой, забыл…» на коммерческих проектах грозит как минимум потерей лояльности клиента, а как максимум — не функционирующим сайтом и полной потерей клиента. Поэтому нужно было как-то этот процесс сделать более технологичным и не требующим лишних действий от меня. Дальше я в очередной раз порассуждаю, как делать правильно, если нужно решение, то переходите к разделу с картинками.
Конечно, самым правильным вариантом будет настройка автоматического распространения кода по выгрузке в Git. Например, в bitbucket есть такая штука — webhook, работает так: когда в битбакет приходят изменения, то срабатывает хук, который отправляет пакет на определенный адрес, и уже на стороне сервера, который принял пакет, можно запустить git pull, чтобы забрать изменения. Очень удобно, я на нескольких внутренних проектах реализовал эту схему, есть определенные нюансы, но про них как-нибудь позже.
Но эта светлая идея мне в нужный момент не пришла, и потребовалось изобретать какой-то выход из ситуации. Как в том мультфильме: «Лучше день потерять, а потом за 5 минут долететь».
Ранее я уже писал про то как я вижу правильную web-разработку, и в частности про поддержку боевых проектов.
Все то, что активно поддерживается, всегда развернуто у меня на машине, на локальном веб-сервере. К счастью, до этой мысли я к тому моменту дорос. Но проблема как разворачивать? Многие туториалы по PhpStorm предлагают отправлять код на сервер при сохранении файла. Если речь идет про сервер разработки, это имеет смысл (хотя скорость обмена файлами с удаленным сервером может расстраивать) Но у меня дев == локальный сервер. Ладно, прекращаем тянуть кота за известные части тела, к делу.
Открываем раздел Deployment.

А дальше как и при любой настройке удаленного сервера, жмем «добавить сервер» (маркер 1), чтобы не загаживать общее пространство, можно установить параметр видимости, чтобы добавленный сервер был виден только для этого проекта (маркер 2). Поле Root path говорит PhpStorm’у где искать корневую папку сервера, это не обязательно должна быть папка самого проекта, например, если у вас на шаред хостинге лежит пяток сайтов, то можно галку 2 не устанавливать, а рут папку настроить на корневую папку всех сайтов. Собственно, маркером 6 обозначены 2 кнопки: «автоматическое определение корня», с большой вероятностью укажет на домашнюю дирректорию или «ручное управление».
Вкладка Mapping важна, если не настроить, то ничего работать не будет. Там нужно настроить: поле № 1 — где локально лежит ваш проект (интересно, а если указать вообще левую папку?); поле № 2 — папка на сервере, где лежит проект. Тут я руководствуюсь таким правилом: «Не доверяй клавиатуре, верь мышке», что в простонародье значит, лучше папки выбирать мышкой из диалогового окна, чем вписывать руками.
Опциональная, но очень полезная вкладка Exclude Path, нужна для исключения папок и файлов из сравнения (Ваша лодка подана, Капитан!). В действительности очень полезная настройка, об этом чуть ниже.
Таким макаром добавляем все наши сервера, например у меня это пока 6 штук. И что дальше? А дальше все просто. В левой части PhpStorm у меня открыта вкладка проект, я выделяю корневую папку проекта

и иду в меню Tool → Deployment → Sync with Deployed to, в диалоговом окне выбираю нужный сервер, жму enter. Откроется еще одно окно, где будут отображены результаты сравнения файлов, если есть различия. Технически и идеологически ничто не мешает сделать тупо выгрузку на сервер, но иногда, сравнение изменений может быть полезно, чтобы случайно не залить не ту ветку, например. И вот тут-то нам пригодится настройка исключения папок. Зачем сравнивать служебные папки CMS или Frameworka, это может быть не очень быстро, во-первых, а во-вторых, они могут не совпадать с локальными файлами. Изменять их все равно не будем, мало ли чего там в продакшене происходит.
Меня через некоторое время достало гонять мышку туда-сюда по меню, а я уже не мальчик какой-нибудь (тем более, что от мыши я отказался в силу определенных соображений, и сейчас пользуюсь исключительно тачпадом). Настроил в keymap сокращение syncdo, и теперь быстрым движением даблшифт (двойное нажатие на левый шифт) и в поле ввожу syncdo, и получаю тоже самое окно, как и для пути Tool → Deployment → Sync with Deployed to.
Серебряной пули тут не получилось. Было бы неплохо, одним нажатием запустить синхронизацию сразу на все сервера, но я не осилил эту науку, поэтому работаем как есть.
Настройка gulp для front-end разработки в PhpStorm

Gulp — это сборщик проектов, который сам по себе ничего кроме организации потоков не умеет. Зато у него есть тьма плагинов, которые умеют все, что надо для front-end. Лично мне надо чтобы мои SCSS собирались в css, а JS минифицировались. Для компиляции css в PhpStorm можно использовать стандартный scss процессор, написанный на ruby, который отлично с этим справляется, но я стал замечать, что при наличии больше 5 scss, каждый из которых по 500-700 строк, в PhpStorm сборка занимает значительные 3-5 секунд, что для меня является долгим. А в одной из статей было сказано, что gulp-sass умеет это делать быстрее. Зерно сомнения посеяно, шило все глубже внедряется в мозг. В общем, на очередном проекте было принято волевое решение попробовать этот ваш Gulp.
Как я уже писал, мне надо не много:
В идеале, надо будет добавить еще сжатие картинок, но я делаю это пока вручную.
Для начале немого поговорим о том, как я организую структуру проекта:

Про стили чуть ниже. Для картинок я создаю 2 папки, те, который имеют отношение непосредственно к дизайну images/, и картинки, которые на этапе прикрутки будут заменены складываем в demoimg/, несжатые скрипты лежат в js/src/, а сжатые в корне js/. Стили мне нравится хранить в одной папке вместе с исходниками, ниже показано как это выглядит.

Не забывайте правильно настроить .gitignore, я надеюсь, что использование Git вошло в привычку, пусть даже кроме вас никто не будет использовать ваши файлы, но git это в первую очередь инструмент контроля версий, а уж потом средство совместной разработки. Мой .gitignore выглядит так:
# Исключим из репозитория папки с картинками .idea/ # Исключение .map файлов *.map *.json # gulp gulpfile.js node_modules
Чтобы работать с Gulp он должен быть у вас установлен, а для этого в свою очередь нужен NodeJS и NPM.
И так, для компиляции SCSS нужен пакет gulp-sass, но этот пакет не умеет генерировать.map, поэтому для его генерации нужен другой пакет gulp-sourcemaps. Для css этого достаточно. Теперь к минификации js. Нужно так же 2 пакета gulp-uglify — сжимает js, а чтобы у файлов появился префикс .min нужен пакет gulp-rename. В архиве пакетов Gulp есть и более эффективные модули, который в одну операцию умеют сжимать и добавлять префикс, но мне не понравилось, что он склеивает все js файлы в один, я хочу чтобы файлы оставались разделены. Для начала из корня проекта инициализируем проект
npm init
Внимательно или не очень следим за всеми пунктами и по необходимости заполняем их. Самое главное главный файл назовите gulpfile.js, установщик об этом спросит. Установка требуемых пакетов совершается одним движением
npm install --save-dev gulp gulp-sass gulp-sourcemaps gulp-uglify gulp-rename
Ключ —save-dev говорит что эти пакеты нужно только для пространства разработки и в продакш идти не должны. В корне проекта появился некий package.json, где указаны все пакеты с которыми мы имеем дело. Нафиг он нужен? Кроме того, что он несет служебную нагрузку, в перспективе я буду его таскать из проекта в проект и установку всех нужный пакетов производить одной командой
npm install
Главное чтобы npm видел этот файл. Он его прочтет и скачает нужные модули.
Собственно, что теперь со всем этим добром делать? Для начала создадим gulpfile.js где напишем слудующее:
'use strict';
var gulp = require('gulp'),
sass = require('gulp-sass'),
sourcemaps = require('gulp-sourcemaps'),
uglify = require('gulp-uglify'),
rename = require('gulp-rename');
Это просто подключение нужных пакетов. Можно открыть документацию к кажому пакету и детально изучить возможности. У меня для компиляции css используется такой код:
gulp.task('sass', function () {
return gulp.src('./css/**/*.scss')
// Для генераии style.css.map
.pipe(sourcemaps.init())
// Собственно компиляция
.pipe(sass({outputStyle: 'expanded'}).on('error', sass.logError))
// Куда положить .map
.pipe(sourcemaps.write('./'))
// Путь компиляции
.pipe(gulp.dest('./css'));
});
Для сжатия js
gulp.task('compressed-js', function () {
gulp.src('js/src/*.js')
.pipe(uglify())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('js'));
});
Задания можно запускать из консоли, но использую PhpStorm как-то это странно. Правой клавишей по gelpfile.js и выбираем пункт Show Gulp Tasks, откроется панель, где показаны доступные задачи

Можно даблкликом запустить любую. Но стоп! С js допустим ладно, периодически ткнуть — ок, но раньше css умел автоматически компилироваться, а теперь как?
Для автоматической компиляции у Gulp есть, так называемые вотчеры (watch). В документации они описаны, они следят за изменением файлов, и при каждом изменении могу запустить ту или иную задачу. Наш код примет следующий вид:
'use strict';
var gulp = require('gulp'),
sass = require('gulp-sass'),
sourcemaps = require('gulp-sourcemaps'),
uglify = require('gulp-uglify'),
rename = require('gulp-rename');
// SCSS compiled
gulp.task('sass', function () {
return gulp.src('./css/**/*.scss')
// Для генераии style.css.map
.pipe(sourcemaps.init())
// Собственно компиляция
.pipe(sass({outputStyle: 'expanded'}).on('error', sass.logError))
// Куда положить .map
.pipe(sourcemaps.write('./'))
// Путь компиляции
.pipe(gulp.dest('./css'));
});
gulp.task('sass:watch', function () {
gulp.watch('./css/**/*.scss', ['sass']);
});
// JS COMPRESSED
gulp.task('compressed-js', function () {
gulp.src('js/src/*.js')
.pipe(uglify())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('js'));
});
gulp.task('compressed-js:watch', function () {
gulp.watch('./js/src/*.js', ['compressed-js']);
});
А панель задач Gulp имеет такой вид

Можно запустить любой вотчер и он будет висеть в процессах, пока его явно не убьешь.
Но я пошел еще дальше и создал общий вотчер, который включает в себя и компиляцию css, и сжатие js, это делается всего одной строкой:
// Смотрим на все
gulp.task('watch', ['sass:watch', 'compressed-js:watch']);
Теперь запускаем один вотчер и при любом изменении js или scss происходят все нужные манипуляции с файлами. Но, на сколько я понял, при добавлении новых файлов вотчер надо перезапускать, по крайней мере у меня он не захотел пережимать js, который был добавлен после запуска.
Конечно, ни что не мешает каждый раз запускать задачу вручную, но IDE предоставляет возможность автоматического запуска задания. Для этого идем в настройки Tool→Startup Tasks

В этом окне слева выбираем добавить новую задачу, и ищем Gulp

И в открывшемся окне добавляем наши вотчеры, хоть каждый по отдельности, хоть один общий.

Вот как бы вот так. Главное, если не настроили автоматический запуск вотчеров, не забывать запускать задачу при старте работы над проектом, а то ничего не получится. Но рекомендую переложить на IDE проблему автозапуска. Пока серьезного выигрыша по времени я не увидел, т.к. не было тяжелых проектов, но то, что вижу на небольших файлах, впечатляет. К тому же изучение новых технологи (пусть даже для одного взятого меня она новая), это всегда хорошо для разработчика, чтобы хоть как-то поспевать за изменяющимся миром.
ИНН 5260488533
+7 993 435 0226
Нижний Новгород, ул. Гоголя, 45а-13
info@sawtech.ru