PhpStorm. Лайфхак: keep-alive automatic upload на коленке

в 11:47, , рубрики: automatic, IDE, keep-alive, node.js, nodejs, phpstorm, upload, Блог компании Rangg, Веб-разработка, метки: , , , , ,

Многие сталкивались с проблемой Automatic Upload в PhpStorm (сюда можно вписать другую IDE с подобной проблемой) при работе на удаленном сервере. Называть ее «проблемой» тоже можно с натяжкой, но тема жива: PhpStorm при заливке измененных файлов каждый раз поднимает новое подключение, что занимает достаточно ощутимое время (у меня уж точно: хостинг-провайдер Hetzner), поэтому приходится ждать несколько секунд прежде чем изменения зальются.

Под катом я расскажу как на коленке набросал скрипт keep-alive подключения с Automatic Upload проекта.

В тексте будет много кода и мало комметариев. Связано это с тем что комментировать там и нечего: для новичков разобраться в NodeJS помогут гайды и статьи (но в это в любом случае JavaScript), а для бывалых код-ревью скажет больше чем я.

Сам скрипт написан на NodeJS — он достаточно прост и всегда находится под рукой, поэтому выбор был очевиден. Подключение я использую SFTP. Итак что нам нужно:

  • Мониторинг файлов на изменение
  • Upload измененных файлов на удаленный сервер

Я решил не углубляться в идеальные для этого библиотеки — не хотелось тратить на эту задачу достаточно много времени. Беглый просмотр интернетов навел меня на 2 простеньких модуля:

  • chokidar — мониторинг файлов
  • ssh2 — ссш-коннект к серверу

Описывать как их устанавливать и как работает NodeJS не буду — гайдов полно на том же хабре.

Файлик я назвал незамысловато deploy.js. Первые строки выглядят просто:

var fs = require('fs');
var Connection = require('ssh2');
var Сhokidar = require('chokidar');
var c = new Connection();

Итак, библиотеки подключили. Первым делом надо подключиться к серверу:

c.connect({
        host: 'habrahabr.ru',
        port: 1500,
	username: 'habr',
	password: 'habrapassword'
});

Как у большинства модулей у ssh2 есть события. Выведем их в лог:

c.on('connect', function() {
	console.log('Connection :: connect');
});
c.on('error', function(err) {
	console.log('Connection :: error :: ' + err);
});
c.on('end', function() {
	console.log('Connection :: end');
});
c.on('close', function(had_error) {
	console.log('Connection :: close');
});

Ну и конечно то с чем мы и будем работать:

c.on('ready', function() {
        ....
})

В этом модуле есть достаточно полезная фича — sftp: достаточно удобный и простой менеджер для работы с файлами:

c.sftp(function(err,sftp){
		if(!err){
			console.log('sftp start');
		}else{
			console.log('sftp err',err);
		}
	});

Когда подключение поднято — пришло время внедрить мониторинг файлов:

			var watcher = chokidar.watch(local_path,
				{ignored: // функция отвечающая за игнорирование файлов. я добавил сюда пути папки SVN и самого PhpStorm
					function(path){
						if(path.indexOf(".idea") >= 0 || path.indexOf(".svn") >= 0 || path == (local_path+'/dpl')){
							return true;
						}
					},
					ignoreInitial:true // параметр отчающий за игнорирование файлов при инициализации скрипта. Если false - будет литься весь проект при каждом запуске
				});

У вотчера есть события add, change, unlink , которые и отрабатывают при манипуляции с файлами. Дело осталось за малым: заставить модуль ssh2 дублировать изменения проекта по sftp:

			watcher
				.on('add', function(path,meta) {

					console.log('upload added',path.replace(local_path,deploy_path));

					sftp.fastPut(path,path.replace(local_path,deploy_path),{},function(err){
						if(err){
							console.log('sftp upload err',err);
						}
					});
				})
				.on('change', function(path) {

					console.log('upload changed',path.replace(local_path,deploy_path));

					sftp.fastPut(path,path.replace(local_path,deploy_path),{},function(err){
						if(err){
							console.log('sftp change err',err);
						}
					});
				})
				.on('unlink', function(path) {
					console.log('remove file',path.replace(local_path,deploy_path));

					sftp.unlink(path.replace(local_path,deploy_path),function(err){
						if(err){
							console.log('sftp remove err',err);
						}
					});
				})
				.on('error', function(error) {console.error('Error happened', error);})

Готово! Файлы заливаются быстрее чем мы табаемся в браузер! По поводу нагрузки — скрипт кушает ЦП примерно как скайп (MacBook Air mid 2012), так что вполне терпимо.

Чтобы не дублировать на каждый проект по деплоеру я набросал легкий Bash скрипт, который бросаю в корень проекта, он уже и запускает наш скрипт.

#!/bin/bash

DEPLOY_PATH="/deploy/path"

DEPLOYER_PATH="/path/to/deploy.js"

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do 
  TARGET="$(readlink "$SOURCE")"
  if [[ $SOURCE == /* ]]; then
    echo "SOURCE '$SOURCE' is an absolute symlink to '$TARGET'"
    SOURCE="$TARGET"
  else
    DIR="$( dirname "$SOURCE" )"
    echo "SOURCE '$SOURCE' is a relative symlink to '$TARGET' (relative to '$DIR')"
    SOURCE="$DIR/$TARGET"
  fi
done

RDIR="$( dirname "$SOURCE" )"
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
if [ "$DIR" != "$RDIR" ]; then
  echo "local_path is '$DIR'"
fi

node $DEPLOYER_PATH local_path=$DIR deploy_path=$DEPLOY_PATH

Ну и в этом случае конечно надо получить параметры в deploy.js

var local_path;
var deploy_path;

process.argv.forEach(function (val, index, array) {
	var item_arr = val.split('=');
	if(item_arr.length > 1){
		switch(item_arr[0]){
			case 'local_path':
				local_path = item_arr[1];
				break;
			case 'deploy_path':
				deploy_path = item_arr[1];
				break;
		}
	}
});

Скрипт прост и подходит для многих других задач. Например можно перезапускать NodeJS приложение на удаленном сервера после заливки файла, или дублировать картинки с окружения разработчика на общий dev сервер.

Прикладываю файл скрипта.

Скрипт был написан примерно за час, поэтому в нем могут быть глупости и банальные ошибки, поэтому прошу не судить строго. Смысл поста — не предоставить идеально работающий код а навести на мысли о возможном решении. Долгие часы я шарился в интернетах в поисках плагинов или хаков, но ничего не нашел. Идея пришла сама собой, с выходом нового PhpStorm, когда увидел поддержку консоли в IDE.

Спасибо за внимание и конструктивную критику!

Автор: Pasa

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js