У меня напрашивается определённые мысли по решению проблемы.
Спишу поделится. Заранее извеняюсь за оффтоп. Разжовываю подробно и со всех сторон. Который раз пишу про архитектуру, и всегда получается очень много . Словами большой кусок кода описать непросто :) Итак напомню проблемы. 1)При возвращении данных в формате ajax у нас возникает проблема с поисковиками, 2)возвращая данные в html, мы обрекаем скрипт клиента работать с хтмл, что ему не всегда удобно первую проблему можно решать делая рендер для сервера и клиента отдельно , что весьма трудозатратно. Однако я сразу необратил внимание на то, что трудозатратно это только в том случае если на сервере и на клиенте разные языки, к примеру PHP + JS. Но ведь связки NODEJS+JS это не касается, тут то один язык ! ================================================== = Это значит что мы можем написать универсальный код который будет работать и на клиенте и на сервере. Звучит неплохо, можно порассуждать как сделать. ================================================== = Для начала назовём этот самый динамический фрагмент страницы виджетом, чтобы обзавестись терминологией. Первое что приходит на ум, сделать виджет большим цельным модулем, который будет подключатся к клиенту и серверу. Однако в этом случае на сервере будут подключаться обработчики событий браузера, которые там нафик не нужны, так как серверной стороне пофиг на события браузера. Да и вообще виджет может быть очень очень большим, и пихать всё в один модуль не айс. Попробуем разбить виджет на части, чтобы подключать в разных ситуациях только нужные части. За принципам разбивания далеко ходить не будем, возьмём проверенный MVC. Тогда получается следующая картина. Каждый виджет состоит из трёх частей. Модель - хранит данные и умеет с ними оперировать. VIEW - умеет рендерить данные в хтмл. Контролёр - поведение виджета (реакция на события). К серверу подключать достаточно VIEW и MODEL К клиенту VIEW,MODEL и контролёр. То есть на сервере при рендеренге страницы,мы используем VIEW которая использует модель. На клиенте используется тот же view с той же моделью, и контролёр в придачу (чтобы он мог реагировать на события). То есть в виджите есть две части(модель и view ), существующие одновременно на двух физических разделённых слоях системы. ================================================== = Как добится их применимости на клиенте и на сервере одновременно ? ================================================== = Очевидно что нужно абстракироваться от платформы. Модель может отдалится от источника данных при помощи специального класс (назовём его PROXY). Иными словами модель не будет иметь доступа к источнику данных напрямую. Она будет работать при помощи посредника, который скрывает от неё истинный источник данных. Если прокси на сервере, будет посредником между бд и моделью,то на клиенте прокси будет посредником между моделью и сервером. последний случай интересен тем, что в реальности прокси между моделью и сервером, это прокси между моделью и сервисом сервера по предоставлению данных. В этом случае на сервис придётся возложить ответственность по проверке прав доступа к данным, для каждой операции. Представление (view) может отдалится при помощи шаблонизатора и какихнибудь хелперов для рендеринга. Тоесть опять же особенности платформ мы пытаемся вынести в сторонние библиотеки, оставляя код виджета чистым от тонкостей платформ. ================================================== = как это приблизительно работает ? ================================================== = Сервер 1) Генерируется страница, на странице обнаружен виджет 2) Подгружается модель и view виджета, в VIEW запускается метод rendeIndex, который рендерит виджет 3) VIEW в процессе рендеринга использует в качествке источника данных модель, модель для загрузки данных в себя, обращается за помощью к прокси, который умеет работать с бд 4) Полностью отрендеренная страница отправляется клиенту. клиент. 1) На страницу подгружаются все востребованные клиентом скрипты.(впрочем это может происходить паралельно с шагом 2) 2) Начинается процесс инициализации, сначало ищется тег в котором находится виджет, затем инициализируется соответственный контроллёр, которому в качестве параметра передаётся ссылка на DOM элемент с виджетом. 3) контролёр, при инициализации может захотеть заполнить модель, в этом случает он даёт модели команду load, модель обращается к прокси, который обращается к сервису на сервере, на сервере происходит проверка прав на доступ, и если всё нормально то данные возвращаются прокси, и он заполняет данными модель. 4) дальше контролёр подписывается на все интерисующие его события. 5) Контролёр ждёт событий. Первый раз рендерить виджет не надо, так как он уже отрендерен на сервере. Когда произойдёт события контролёр просто вызовет соответствующий метод у view для того чтобы он отобразил данные из модели. ================================================== = Какой профит ? ================================================== = 1) Решили проблему с поисковиками. - Виджеты рендерятся на сервере, когда генерируется страница. 2) Сокращён срок разработки - Мы не дублируем код на сервере и на клиенте. 3) Сохранена функциональность клиентских скриптов, нет обязаловки в передачи клиенту HTML, клиент получает данные в формате JSON, которые попадают в модель, клиент этими данными распоряжается по своему усмотрению. 4) Мы получили возможность создавать очень сложные виджеты, за счёт разделение кода виджета на логические части. ================================================== = Можно ли для построения сайта использовать только плагины ? ================================================== = Кто работал с MODX тот в курсе что страницы там по сути статичный HTML, а весь динамически сгенерированный контент создают снипеты. Подобный подход можно применить и здесь, возвращать только статичный html с сервера, а весь динамически создаваемый контент в нём, могут создавать плагины. То есть страница будет просто рамкой в которую встроены плагины. Конечно всё вешать на плагины не обязательно, но идея на мой взгляд забавная. Ниже я ещё допишу пару топиков с поянениями, и примерами кода. Также жду ваших соображений по выше написанному. |
Вариант реализации
Доброго дня, предложу вариант, с которым обычно работаю:
1. Запрос получает фронт-контроллер, единая входная точка веб-приложения. 2. Он определяет, какая модель данных затребована (на шаблоны ему пока побоку), в данном случае - СписокМудаков. 3. Запрашивает у Model-слоя необходимую модель. По сути - набор объектов, в родном для системы формате (в вашем случае - JavaScript-массив Мудаки[] + отчет об ошибках, если нужен: Ошибки[]). Никаких потерь на сериализацию на данном шаге! 4. Определяется шаблон. Варианты: - HTML, JSON, XML...; - редирект (этому пользователю нельзя видеть список мудаков); - сообщение об ошибке (вместо запрошенных данных) в нужном формате; - ...etc; Фишка определения шаблона именно на этом шаге (а не на первом-втором) в том, что мы адекватно можем отреагировать на ошибки формирования модели, ограничения прав доступа и т. д. 5. Модель отдается соответствующему шаблонизатору. Фишка, опять же, в том, что видов шаблонизаторов здесь можно подключить сколь угодно много (HTML, XML, JSON, ...). 6. Шаблонизатор сериализует модель должным образом и отдает клиенту. Тип подключаемого шаблонизатора может определяться параметром запроса или урлом. Например, по умолчанию генерим HTML, при наличии в запросе &format=json - генерим легковесный JSON. NGINX на входе становится не обязательным (и даже не желательным в контексте работы фронт-контроллера), но вполне может использоваться для выдачи статики. В общем, ничего ничему не мешает. Успехов в серверном JS! |
Цитата:
Цитата:
Цитата:
Цитата:
lsync, по поводу второго и третьего пунктов. При ajax-запросе всё просто, нужны одна модель - массив мудаков. При обычном запросе, помимо этого массива, нужен уже набор этих моделей. Так же и при ajax-запросах возможно понадобятся несколько моделей в одной пачке. Если определение этих наборов переложить на контроллер - он будет сильно разрастаться. Поэтому я и разделил на несколько контроллеров и назвал их сервисы. Собственно, получается то, о чем я писал в первом посте. |
Цитата:
Цитата:
2. Разделить на несколько контроллеров и назвать их сервисами - это супер, но то, что вы написали в первом посте, требует наличия внешнего роутера. Он ни к чему в данной цепочке - лучше сделать его внутренним. Причины:
Хотя есть и серьезное преимущество - внешний роутер это плюс к легкости масштабирования. Так что надо взвешивать конкретную ситуацию. Цитата:
|
Так, стоп.
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Обычно для формирования одной страницы сайта вам придется обратиться к нескольким своим сервисам (блочный дизайн, так?), отсюда и вызов нескольких сервисов на один HTTP-запрос. И отсюда же - необходимость логики для формирования всей страницы из кирпичиков независимых сервисов: Пришло: http://domain.com/forum/page=3 Вызвали свои сервисы: - getMenu; - getUserData; - getPosts; - getAd; - get... Положили все это в дерево ответа. Отдали шаблонизатору, отрендерили, вернули результат в виде HTML страницы. Пришло: http://domain.com/api?getAd=8 Вызвали: - getAd; Положили в дерево, отрендерили в JSON, вернули. В примере выше "getAd" - ваш сервис, он независим от остального и всегда выдаёт одинаковую модель, хотя и вызывается из совершенно различных контекстов. А фронт-контроллер определяет, какой набор сервисов вызвать согласно запрошенному URL, и в каком шаблоне отрендерить результат. Для простоты понимания я бы предложил ввести еще один термин - Flow (Поток). Тогда верны утверждения: - URL определяет, какой Flow будет отработан; - Flow содержит нужный набор сервисов; - Фронт-контроллер выполняет Flow, вызывая нужные сервисы и сохраняя ответы в результирующую модель; - Фронт-контроллер определяет, корректно ли выполнен Flow, и принимает решение о выборе шаблона; - Шаблонизатор рендерит модель в указанный контроллером шаблон. |
В догонку добавлю, что несмотря на кучу терминологии и длинные объяснения принципов работы, на практике подобная система реализуется на любом языке за 15 минут (при условии наличия шблонизатора), без каких-либо фреймворков, и самое главное - весьма эффективно растет и масштабируется, без появления каши в системе.
|
lsync, я понял, мы под разными терминами подразумеваем разные вещи. Я говорил о:
Цитата:
Цитата:
Цитата:
Поэтому я и написал, что одновременно не могут быть вызваны несколько сервисов. Перед сервисами - роутер (nginx), разруливает, на какой сервис пришел запрос. Цитата:
Цитата:
Цитата:
Если такая терминология подходит, предлагаю переходить на неё. Если нет - объясни какие моменты считаешь нелогичными/непонятными. |
Ну, раз взаимопонимание достигнуто - всё супер. По сути, я хотел бы только выделить из написанного мной выше, что именно предлагаю откорректировать в исходном алгоритме:
Цитата:
Цитата:
Цитата:
Цитата:
|
Цитата:
Цитата:
Цитата:
|
Часовой пояс GMT +3, время: 23:48. |