Заморочился я автообновлением странички в браузере на таскаемом с собой iPad при разработке NodeJS/ExpressJS-приложений, чтобы видеть все изменения на лету.
Под катом — как очень просто сделать из мобильного гаджета средство живого просмотра разрабатываемых веб-приложений.
По разным причинам статья LiveReload на Node.js мне не помогла. По каким? Всё просто — там дядьки grunt-ы с gem-ами обсуждают. А я только пришел к NodeJS/Express. Не пугайте меня короче :)
Зачем это надо?
Для удобства, для чего же еще. Пересев на MacBook Air понял, что это тот инструмент, который я хотел. Минусом было недостаточное количество места на мониторе и отсутствие AppleTV для решения сабжа (для его замены заказал Tronsmart T1000 MirrorT2 со значительной скидкой, посмотрим как он справится с задачами, но это уже другая история), хотя идея сидеть перед телевизором для живого созерцания результата деятельности не очень нравится…
Глядя на зоопарк разноплатформенных гаджетов, подумал — а почему бы не попользовать таскаемый всюду вместе с макбуком айпад в качестве отображения творимого? Да еще и чтоб пальцем в иконку не попадать…
Второй монитор из планшета? Нее.
Сначала подумалось — вот же, купить AirDisplay в аппсторе (или его аналог за меньшие деньги, например iDisplay), поставить сервер, и — вуаля. Но это решение несколько иных задач, наверное полезных и нужных. Но не моей.
Тем более Tronsmart уже выслан нашими братьями с поднебесной.
Действуем правильно.
Мне очень не хотелось созерцать результат на десктопном браузере, а хотелось именно в нативном гаджетном (том же Safari).
И очень удачно, что есть решения умельцев для дерганья сервера ноды при изменении файлов проекта (nodemon, supervisor и иже с ними). Забегая вперед: мой выбор пал на supervisor ввиду его более отзывчивой работы.
Хорошо, сервер перезапустится при Command-S / Ctrl-S (кстати, на Windows метод тоже работает). Как теперь заставить браузер освежить контент? И снова краткий гуглеж вывел меня на reload.
Что написано в описании модуля reload:
Node.js module to refresh and reload your code in your browser when your code changes. No browser plugins required.
Отлично, то что нужно. Вооруженный целыми двумя тулзами я и сел за ваяние некоего чуда:
Тестировать будем на чистом express-приложении:
$ express
Тянем зависимости:
$ npm i
Ставим supervisor:
$ npm i supervisor -g
и reload:
$ npm i reload --save-dev
Всё, подготовка окружения закончена.
Теперь нужно подпилить приложение-заготовку согласно документации:
/app.js:
...
var reload = require('reload');
...
var server = http.createServer(app);
reload(server, app);
server.listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
/views/layout.jade:
head
script(src='/reload/reload.js');
Запустим наш супер superserver на отслеживание изменений в файлах .jade:
$ supervisor -e jade app.js
и убедимся, что наш «компьютерный» браузер показывает именно то, что мы ждем, по адресу localhost:3000:
Для проверки живого общения браузера с сервером, поменяем исходный файл /views/index.jade
extends layout
block content
h1= title
p Welcome to #{title}
на:
extends layout
block content
h1= title
h2 Привет!
p Welcome to #{title}
и получим живое обновление с названием LiveReload:
Работает, черт возьми!
Грабелек? Их есть у меня!
На радостях бежим к нашему гаджету, в моем случае к iPad, набираем в адресной строке 0.0.0.0:3000 (ip-адрес машинки с запущенным NodeJS-сервером), получаем ожидаемый результат:
далее возвращаем код /views/index.jade к исходному, без h2 Привет!, сохраняем его и… получаем фейл:
Причем, если страницу обновить руками — всё отобразится как и должно быть. Засада… DeadReload…
От печальки до радости...
Пораскинув мозгами, поковыряв всяко-разно, и ничего не починив и не поняв происходящего, я тупо сейвил текст и обратил внимание, что на iPad в такт моим сейвам сверху на мгновение показывается нативный анимированный лоадер (или как оно называется, иконка загрузки короче).
Ага! Вот ты и попался. Видимо, браузер слишком рано хочет сделать себя LiveForever. Надо ему подпилить чего-нибудь…
Полез в исходники reload-а в /node_modules/reload/lib/ (как я сразу не додумался, стыд-позор мне), и нарыл там 4 файла:
reload.js, reload-client.js, reload-server.js, sockjs-0.3-min.js.
Сразу же заинтересовал reload-client.js, смотрим, и в самом начале файла, прям во второй строчке, находим решение всех проблем человечества:
;(function refresh () {
var RLD_TIMEOUT = 300;
var sock = new SockJS(window.location.origin + '/sockreload');
sock.onclose = function() {
setTimeout(function() {
window.location.reload();
},RLD_TIMEOUT);
};
})();
Подытожим, господа!
Опытным путем, сделать бесфейловый LiveReload мне помогло минимальное значение RLD_TIMEOUT = 700;
На этом всё. Полученным решением я доволен, всё работает так, как мне, далекому от веб-разработки и веб-магий человеку, и нужно было — легко и непринужденно, главное — без заморочек и уговоров жаб.
Автор: beaverBox