modNodejs - Интеграция Nodejs в MODx
Всем доброе утро. Сегодня представляю на всеобщее обозрение компонент над которым я потел последние несколько дней.
Заголовок говорит сам за себя, это интеграция Nodejs в MODx.
Так зачем он нужен? Для realtime! Как сказал Николай: «технологии диктуют».
Простейший пример: в minishop2 поступил заказ, а менеджер гуляет по админке\сайту, вот что он увидит:

Без перезагрузки страницы и тд, можно выполнить любой js по наступлению эвента.
Вот весь путь появления этого уведомления:
1. Отправка эвента в nodejs из modx
2. Обработка эвента в nodejs и отправка в браузер (всем пользователям с группой администратор)
3. Получения эвента на стороне браузера
Компонент позволяет «расширять» логику как плагинами modx так и плагинами для nodejs.
Можно обращаться к modx'у из ноды для получения чего-либо, пример:
1. Создаем плагин
2. Создаем файл %filename%.js в папке /modnodejs_components
3. В браузер добавляем
4. Где угодно вызываем эвент
Таким образом вы можете использовать nodejs как вам угодно. Messenger будет написан на этой связке.
При каждом запросе с ноды в модкс идет проверка кук (если инициатор пользователь) и токена.
Жду пулл реквестов и пожеланий, надеюсь связка кому-нибудь да понадобиться. Потихоньку буду обновлять гитхаб.
Исходники https://github.com/but1head/modNodejs
Оставил коменты в коде насколько это возможно.
Переносим папку modnodejs_components и modnodejs.js в s****/ В файле modnodejs.js указываем токен (придумываем сами)
Выполняем в консоли команды:
Устанавливаем компонент.
В системной настройке modnodejs_token указываем токен, который указали в modnodejs.js
>>> Отправить автору спасибо за бессонные ночи ;)
Заголовок говорит сам за себя, это интеграция Nodejs в MODx.
Так зачем он нужен? Для realtime! Как сказал Николай: «технологии диктуют».
Простейший пример: в minishop2 поступил заказ, а менеджер гуляет по админке\сайту, вот что он увидит:

Без перезагрузки страницы и тд, можно выполнить любой js по наступлению эвента.
Вот весь путь появления этого уведомления:
1. Отправка эвента в nodejs из modx
case 'msOnCreateOrder':
$modNodejs = $modx->getService('modnodejs');
$modNodejs->emit('msOnCreateOrder', $msOrder->toArray());
break;2. Обработка эвента в nodejs и отправка в браузер (всем пользователям с группой администратор)
socket.on('msOnCreateOrder', function(data){
var data = JSON.parse(data);
io.in('Administrator').emit('msOnCreateOrder', data);
});3. Получения эвента на стороне браузера
socket.on('msOnCreateOrder', function(data){ ... });Компонент позволяет «расширять» логику как плагинами modx так и плагинами для nodejs.
Можно обращаться к modx'у из ноды для получения чего-либо, пример:
1. Создаем плагин
case 'OnNodejsRequest':
if ($action != 'test-event-from-nodejs' ) return;
$modx->event->_output = array('param2' => 2);
break;2. Создаем файл %filename%.js в папке /modnodejs_components
module.exports = exports = function(socket, io, onlineUsers){
socket.on('test-event-to-nodejs', function(data){
var data = JSON.parse(data);
// data = {param1: 1}
modx.request('test-event-from-nodejs', {
param1: data.param1,
}, function(response){
// response = {param2: 2}
// отправка всем онлайн пользователям
socket.broadcast.emit('test-event-to-browser', response);
});
});
}3. В браузер добавляем
socket.on('test-event-to-browser', function(data){ ... });4. Где угодно вызываем эвент
$modNodejs = $modx->getService('modnodejs');
$modNodejs->emit('test-event-to-nodejs', array('param1' => 1);Таким образом вы можете использовать nodejs как вам угодно. Messenger будет написан на этой связке.
При каждом запросе с ноды в модкс идет проверка кук (если инициатор пользователь) и токена.
Жду пулл реквестов и пожеланий, надеюсь связка кому-нибудь да понадобиться. Потихоньку буду обновлять гитхаб.
Исходники https://github.com/but1head/modNodejs
Оставил коменты в коде насколько это возможно.
Установка Node.js
Переносим папку modnodejs_components и modnodejs.js в s****/ В файле modnodejs.js указываем токен (придумываем сами)
Выполняем в консоли команды:
npm install socket.io
npm install forever
npm install request
node_modules/forever/bin/forever start modnodejs.jsЕсли в консоли не возникло ошибок — сервер запущен и все прекрасно работаетУстановка modNodejs в MODx
Устанавливаем компонент.
В системной настройке modnodejs_token указываем токен, который указали в modnodejs.js
>>> Отправить автору спасибо за бессонные ночи ;)
Комментарии: 94
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
перепутав консоль с арендованным сервером. Таким образом узнал что на modhost есть нода)
p.s. Василий добавьте на главной modhost что есть nodejs, мало кто об этом знает по одной заметке полугодовалой
Ещё раз спасибо Автору, так держать!!!
Fi1osofFi1osofFi1osofТолько хотел написать отдельный топик про выложенный node-клиент для нашего чата, а тут такое… Ну, тогда не буду писать отдельного топика, просто ограничусь комментом (сорри за оффтоп).
Итак, на днях я писал, что мы разрабатываем автономный node-чат (его работу можно увидеть на главной странице нашего сайта). Вопрос: хочет кто-нибудь себе такой же? Если да, то вот он: www.npmjs.com/package/node.social-client
Конкретно этот компонент — не полная версия всей системы, а только веб-сервер с чат-клиентом. Для полноценной работы ему еще нужен отдельный сервер, обрабатывающий непосредственно запросы. Как написано в ридми, вы можете использовать для этого наш сервер wss://modxclub.ru:8100 (эти сообщения будут видны на главной странице нашего сайта). Если кому-то нужен выделенный сервер для тестов, пишите в личку, подниму (бесплатно только сегодня). Вторая часть системы (уже сам чат-сервер) появится чуть позже.
Если вдруг кто пропустил сообщение Василия по поводу где можно развернуть такой сервер, уточняю: на modhost.pro
Fi1osofВесь JS/HTML-фронт тоже имеется, включая JS-чата.
Там, конечно, немного АДъ, так как это все еще эксперименты, но разобраться, думаю, не дофига дело. Чтобы пересобрать фронт со своим измененным кодом просто переходим в папку /public/chat, выполняем команду npm install, чтобы установились все пакеты нужные.
Придется подождать не одну минутку, там много пакетов устанавливается. Когда все установится, вы увидите подобное:
После этого выполняем команду webpack -w (запустится сборщик, прослушивая изменения файлов). Когда вы увидите такое (опять-таки, возможно через пару-тройку минут):
можно будет файлы править.
К слову, использовалась вот эта заготовка фронта: github.com/MODX-Club/modx-shopmodx-frontend
Она же используется и в ShopModxBox, то есть там можно таким же образом пересобирать фронт.
То есть, если кому интересно, может сап попробовать поправить фронт (к примеру, добавить звуковые уведомления о новых сообщениях). И даже не лезя в серверную часть самого чата, можно получить свой собственный клиент (с оговорками, конечно, но все же).
Fi1osofС ее помощью запросы на node-сервер без проблем слать. Сампл:
Fi1osofP.S. на ноде сокеты реализованы на вот этим модулем: www.npmjs.com/package/ws
Собственно запрос в ноду из modx выглядит так
А сокетио выбрал тк это как минишоп, только для ноды. Там же и куча ништяков и апи для ноды и фронтэнда.
Fi1osofЯ не придираюсь, я просто пытаюсь понять для себя. Это и для меня все новое и я не один час потратил на поиски подходящего механизма для отправки запросов на сервер средствами php. Меня мой способ устраивает, потому что он отправляет запросы именно по протоколу ws://, ровно так же, как эти же запросы идут из браузера. Крайне не радует перспектива использовать два отдельных протокола и формировать разные форматы данных.
У тебя так же и на стороне браузера формируются запросы?
Думаю 4 команды в консоли стоят результата :)
Отправил в modstore.pro.
Возможно это https://github.com/foreverjs/forever-monitor подойдет
Fi1osofЕсть у меня один проект, где планировалось вывести на карте 50к точек, много всяких карт перебрал и тд, все было долговато (около 2х секунд, т.к. файл точек весит около 10мб). Потом подумал зачем отдавать все это дело клиенту, решил написать сервер на ноде для «порционной» выгрузки в пределах видимости. Вот что получилось:
s8276.h7.modhost.pro/demo/ на карте размещен кластер на 1.000.000 точек (вес файла 135мб), даже с телефона отрабатывает моментально. Выложил все исходники на github.com/but1head/supercluster-nodejs, может кому-нибудь пригодится.
Fi1osofМне как раз на одном проекте нужна гугл-карта с кластеризацией. От яндекс-карт думаю отказаться.
Во время тестов 2гис, гугл и яндекс погибали, все было оч долго. Яндекс еще как-то держался, но в его гроб последний гвоздь заколотил дизайнер с такой цветовой схемой. Вообще спасибо разработчикам supercluster ( www.mapbox.com/blog/supercluster/ ), очень и очень быстрая штука с поддержкой браузера\ноды из коробки. На гите вполне себе рабочий пример. Еще думаю добавлю проверку файла на изменение, чтоб точки обновлялись когда в бэкенде менеджеры копаются.
Fi1osofFi1osofFi1osof1. Из админки постоянно идет долбежка на несуществующий адрес.
joxi.ru/RmzXOWVu0RGQbA
2. Зачем ты жестко прописал адрес куда отправлять запросы? Пришлось хардом заменить на нужный адрес.
3. Зачем ты вот здесь пишешь в начале 42? Я на своем сервере ловлю ошибку разбора JSON-строки.
Вот если все это поправить, то можно использовать его для запросов на произвольный ws-сервер по протоколу ws://. А вот wss:// судя по всему нельзя?
Себе я собрал простенький компонент websoketphp, вот он без проблем отправляет запросы на такие сервера ( в том числе и по ssl). Используется выше указанная библиотека websoket-php. В рамках пакета вызов выполняется просто.
Сейчас выложу его тоже в модстор, будет бесплатным. Он понадобится под анонс другого моего компонента.
2) моя связка на сокет.io, на ноде вылавливаются эвенты через сокетио а не «голая нода»
3) JSON.parse(data)
Я не могу предположить зачем слать запросы на кучу разных серверов, когда будет использоваться один.
По поводу 42 в начале — я долго ковырял, сокеты не принимали запросы без такой конструкции (где-то на гитхабе выловил)
Fi1osofНу а зачем на это завязываться? Дай метод типа IoSend($data), который сформирует данные нужные (и адрес нужный), и отправит через голый send($address, $data), который умеет слать данные в любом формате на любой адрес.
Думаешь, я не знаю этого метода? :) Но твой модуль шлет запросы типа 42["/", "{\«type\»:\«sdfsdf\»}"]. Попробуй в той же консоли выполнить print_r(json_decode('42["/", "{\«type\»:\«sdfsdf\»}"]',1)). Что он тебе даст? Ничего. Потому что 42 в начале бьет все. Надо просто '["/", "{\«type\»:\«sdfsdf\»}"]'.
А почему не использовать несколько серверов? Зачем вообще под это затачиваться. Сейчас это выглядит как телефон, в который зашили непереустанавливаемое ПО и который звонить может только на один определенный номер.
Вот посмотри сюда: stat.modmonitor.ru/
Мне слать данные нужно туда с разных сайтов. Вот через твой модуль не получилось этого сделать. Через мой получилось.
2) Потому что это самое удобное решение как кажется мне
3) У меня все прекрасно принимает через JSON.parse()
4) А зачем использовать несколько серверов?
Посмотрел, ты пишешь свое решение под свое решение, а я не пишу решение под твое решение. Ты щас предлагаешь подстраивать компонент под твои нужды, но то что ты хочешь уж слишком не «общее решение». Как много слов «решение»… Короче говоря это пример обработки, если кто-то строит серьезные проект то и делать всю обработку «для себя» надо.
И ты уже не первый раз говоришь по ws, почитай про инструмент который я использую socket.io/docs/ может отпадут дальнейшие вопросы
Fi1osofОк, не вопрос, не буду больше тебе надоедать. Ты хочешь делать свой продукт лучше, но не слушать никого. Только зачем это писать? Я попробовал, и дал комментарии/пожелания. Может ты не их хотел слышать, а «комплименты»? Комплименты приятны, конечно, но не делают продукт лучше.
$monodejs->emit('event', data); не вернет ответа, это отправка запроса в ноду и далее за обработку отвечает нода, она уже может из себя слать что и куда угодно, как минимум обратно в modx (modx.request('action', data, callback)).
Следовательно ты хочешь отправить запрос с modx в чужую ноду. И получить ответ внутри php, но php завершит процесс до ответа. Можно конечно извернуться и дать ответ, но что в это время будет делать «пользователь» сайта? Ждать ответа?
На примере карты, например, получает ответ браузер по get параметрам, но это браузер а не php.
Может быть я мало осведомлен в логике работы связки пыхи и ноды, но я не вижу смысла слать запросы на чужие сервера. Приведи пример где не только тебе будет полезно послать запрос из модкс куда-либо, и я начну над ним думать. Сейчас ты предлагаешь сделать так, как тебе удобно. Я не вижу в этом смысла для «всех». Добавить эти хотелки не проблема.
И да, каждый сокет (из ноды) проверяет сессию в модкс, если нет сессии — отключается не давая выполнять дальнейшие действия.
А вообще по таким вот обсуждения я уже предлагал тебе общаться в слаке да бы не захломлять тему.
Fi1osofНе захламлять тему чем? Информацией по твоему же компоненту? Не задавай сейчас ответных вопросов, я не буду на них отвечать, диалог закончится.
shop2.ru
shop3.ru
modxclub.ru — нода
у всех стоит modnodejs в настройке modnodejs_host прописан modxclub.ru
Далее ты рулишь всеми соединениями, но тут уже придется переделывать логику сервера, ввиду того, что проверяет сессиию он на одном modx
e. То что ты хочешь не общее решение, а конкретно под тебя. Вот мне например не нужно собирать данные с кучи сайтов, каждый сайт это отдельный клиент и тд. А ты строишь какой-то проект мультистатистики и хочешь готовое решение использовать.
Еще раз, то что я предлагаю это работа ОДНОГО nodejs сервера с одним MODX (не важно кол.во контекстов\доменом). Я не сомневаюсь что кому-нибудь поможет то, что я сделал, да и на гитхабе все исходники, кому нужно разовьет проект для себя, кому-то хватит того, что есть.
Давай закончим. Если хочешь что-то предложить — пул реквест на гитхаб или личка.
Мне кажется, что логичнее, делать связку ноды и и пхп что бы нода была фронэнд сревером, а пхп, бэкэнд сервером. На сколько я понимаю что реквест-респонс щас такой: клиент-пхп-нода-пхп-клиент. А если б нода была фронт сервером, то тогда такх ситуаций не произойдет:
Но тогда возниакет вопрос — зачем использовать в принципе пхп :)
Но конечно такое решение прибавляет время реквест-респонс для конечного пользователя.
Автор, поправьте, если ошибаюсь.
На этой сборке у меня написана система личных сообщений, скоро выложу.
я так полагаю что реализовать данную связку можно архитектурно разными способами
А конкретно в случае который обсуждал Автор и Николай, мне не понятно зачем делать модикс прослойкой между ноудом и клиентом. Пусть клиент сразу общается с нодой, и нода рулить клиентскими реквесатми — респонсами. И тогда, вопрос больше к Николаю, зачем в обще в данном вопросе нужен модикс? Ведь, для него остается мало задач, и не понятно зачем его в принципе использовать.
Fi1osofЭто похоже на Event-API в слэке. Есть два режима:
1. Отправить самостоятельно запрос MODX-у и «узнать» что у него там нового есть.
2. MODX сам шлет запрос ноде и говорит «у меня такие-то новости».
Но вот браузерному клиенту конектиться к ноде через php действительно не за чем, это можно делать напрямую. Максимум, в ноду можно прописать авторизацию или проверку доступа пользователя через запрос к MODX-у.
Браузер конектится к ноде, она в свою очередь проверяет сесиию в пхп запросом в modx.
Fi1osofфротнэнд
node
Далее из ноды делайте что хотите. Хотите обращайтесь в Modx, шлите ответ обратно, подключайтесь к любому апи и тд.
Конкретно моя «связка» включает для себя ВОЗМОЖНОСТЬ соединиться с модкс, если вам это не надо — не делайте, мы все же на modx.pro сидим а не на zachem-modx-v-nodejs.pro
Я поставил и попытался попробовать.
Сделал все по иструкции и добавил плагин на загрузку страницы:
У меня в итоге вот такая ошибка в консоль браузера сыпет:
я что-то забыл?
через несколько часов обновлю
p.s. теперь modnodejs_host должен быть указан как http(s)://site.ru:9090 (при установке указывается автоматически). modnodejs_port более не используется.
github.com/but1head/modNodejs/commit/ad3bd175e15b434a25173aab17971e47ddc55a29
Напиши в личку (контакты в профиле), ибо ты сообщение отредактировал.
node modnodejs.js
и смотри что в консоли. перед выходом с консоли снова
node_modules/forever/bin/forever start modnodejs.js
ибо node modnodejs.js будет работать пока подключен по ssh
stackoverflow.com/a/38402346/5666675
попробовал стрелочные функции переписать на обычной синтаксис:
на сервере node modnodejs.js ошибок не выдает, но в косоли браузера все еще траблы
Придумать свой token — придумал и прописал
DOMAIN — я так полагаю это домен сайта, верно?
А дальше написано что эти данные нужно указать в системных настройках
Настройка токена всё ок —
А вот modnodejs_domain(так написано в описании репозитория) — я такой не нашёл, есть modnodejs_host и что в ней нужно указывать всё таки — домен или хост с портом, который слушает node сервер?
Видимо я слишком запутанно в 5 утра написал.
В modx в modnodejs_host пишем: site.ru:9090 и modnodejs_token: 123456
В node_modules/modnodejs-server/index.js в config.domain: site.ru (или любой другой, куда будут идти запросы в modx) и в config.token: 123456
Обновлю инструкцию.
ток цифры 1\2\3 не хотят работать, при правке все норм
после выполнения выше указанных действий нужен перезапуск ноды
Обновил инструкцию установки
Автор молодец, будущее прямо здесь!
Будет что-то вроде, файл придется создавать вручную.
Вообще пообщавшись с парой человек, как я понял, в ноде не используют «готовые решения», каждое приложение пишется «под себя» и использует просто другие модули. Проще говоря это не минишоп\тикетс из коробки и такого там не добиться, т.к. при обновлении все изменения затрутся (а в ms2 папка плагинов не трется как и сами плагины в modx).
Таким образом мое утопичное желание расширять modnodejs-server добавлением файлов в /plugins потерпело крах в зародыше.
Есть ведь модуль modnodejs-server, в нем можно прописать конфиг, а также функцию на просмотр и возврат содержимого директории.
А в самой директории уже файлы .js с кастомными эвентами. Запрос идет только к modnodejs-server, где модуль работает только как мост между файлами из папки
upd. чтобы при обновлении npm вся папка не затиралась, может сделать подключаемые эвенты отдельным пакетом? и тогда перед обновлением делать unlink, а потом снова link
npm link modnodejs-server
и unlink при обновлении modnodejs-server'а, чтобы не пересобирать modnodejs-packages
или это как-то по-другому работает?
Пытаюсь запустить, но в менеджере выдаёт ошибку консоль:
Содержимое файла как тут gist.github.com/but1head/d7997501b066513281067617e4a21c7c
Смотрю исходники страницы:
И ещё в консоли:
Вроде всё сделал по инструкции.
Заранее спасибо за комментарии и помощь!
Не на столько всё плохо)
Не подскажите, как удалось решить?
Проблему с путями к socket.io.js в core/components/modnodejs/model/modnodejs/modnodejs.class.php исправил.
* у нее есть свой error log
* * если запустить ноду «node app.js» то она даст ошибку в консоль
Сама нода запущена:
Запускал по твоему гайду.
Вытолкну своё предложение. Что если установить на сервер с MODX nodejs + к нему какой-нибудь быстрый js-шаблонизатор. pug, например, или bemtree со всей бэм-связкой вообще. Они же все наверняка работают в разы быстрее, чем встроенный шаблонизатор MODX или даже smarty. Это должно увеличить и (и без того не медленную но всё же) скорость загрузки страниц. Шаблоны тогда придётся держать в файлах, а не в базе — слегка неудобно, но задумка показалась мне здравой, вот только времени свободного очень мало для скорейшей реализации.
Как думаете — небесполезно оно будет?
Fi1osofВыглядит сайт пока не очень, но под капотом там очень серьезно получается.
Наиболее интересные моменты:
1. Сайт отображается без JS ровно так же, как и с JS (отрисовка происходит на стороне сервера).
2. По тестам гугла 94/100 баллов (картинки не оптимизировали, и ответ от сервера пока не очень).
3. Отдельная песня — работа сервера. Запрос идет не сразу на MODX-сайт, а проксируется нгинксом на node.js. Тот, если надо, отправляет запрос на MODX на отдельный порт, получает ответ от MODX-а, обрабатывает его (с отрисовкой на сервере) и возвращает конечный код. Сам же ответ от MODX-а идет не в HTML, а JSON (для этого переопределен modResponse-класс). Вот так примерно это выглядит:
Шаблонизация обеспечивается material-ui
Но самая гордость — это редактор на базе draft-js. На него особенно много времени ушло. Это потрясающая штука! Фишка в том, что все видимые сообщения — это все отдельные редакторы, просто в режиме readonly. И все эти сообщения отрисовываются из исходных данных в формате JSON. В одно сообщение можно закинуть сколько угодно различных информационных блоков, каждый из которых потом редактироваться может как самостоятельная сущность. К примеру здесь мы имеем различные блоки кода (с самостоятельными режимами подсветки).
Если кликнуть Редактировать, то редактор просто переходит в состояние readonly=false и становится полноценным редактором, без подгрузки каких-либо данных с сервера. И сразу видно как оно будет выглядеть в конечном итоге, и после сохранения оно будет выглядеть ровно так же, как и в режиме редактирования.
В общем, при желании можно много всего навернуть, но, все это реально очень сложно. Поверьте на слово. Наша команда два месяца с головой была в изучении всего этого, и только сейчас можно сказать что мы боле менее что-то освоили. Использовать это на мелких сайтах — очень сомнительно. Сложность проекта будет расти сильно, риски тоже, а вот реальная отдача не особо. Но для сервисов можно действительно крутые вещи получать.
Fi1osofВопрос: если у меня 10 доменов связаны с одной установкой MODX
значение config.domain указать для любого одного?
PS с Nodejs дел не имел ранее.
Хочу оповещать посетителей всех доменов и поддоменов о появлении новых статей на сайте. А доменов+поддоменов именно 10 уже.
joxi.ru/1A5QnldhnPzxjA
Ошибка что нет файла, его действительно нет. Смотрел на гите там тоже нет.
вроде процесс ноды запустился
joxi.ru/4Ak0YP5Iy40DMr
что не так? куда копать примерно?
joxi.ru/eAO0K3BIxg6Per