geektimes

Cобрать лучшее из двух миров — фреймворков и CMS

  • пятница, 28 ноября 2014 г. в 02:10:33
http://habrahabr.ru/post/244311/

Четыре года — это в IT уже долгострой. Именно столько, и даже чуть больше времени мне понадобилось чтобы довести CleverStyle CMS до версии 1.0, до состояния когда архитектура устаканилась, имеется достаточная функциональность и целостность системы как таковой, все найденные баги исправлены, и основные сценарии работают без проблем.

Получилось создать что-то среднее между фрейворком и, собственно, CMS, как раз то, что нужно для разработчика, и хочу поделиться этим с сообществом.

Уверен, многим не хватало именно такого решения, это подтверждается многочисленными вопросами на том же Тостере и долгими ветками комментариев под ними.

Обязательно нужно объяснить почему


Сложность, избыточность, гибкость, функциональность и скорость.



Я не нашел решения, которое имело бы удовлетворительный для меня баланс этих параметров (безопасность тоже, но это очевидно и подразумевается само собой изначально).
CleverStyle CMS — это не CMS в привычном смысле, это CMF, выше фреймворка по уровню архитектуры но ниже и гибче CMS.
В связи с таким позиционированием получилось очень удобное решение в первую очередь для разработки уникального функционала, так как есть большинство необходимых инструментов, за которыми не нужно далеко идти, не нужно настраивать, а можно сразу использовать и получать результат.

Отличия в сравнении с фреймворком:
Скрытый текст
Есть отличная статья в тему, которая немного проливает свет на мое к ним отношение Почему я ненавижу фреймворки

  • существенно меньше слоев абстракции
  • как следствие проще и прозрачнее структура
  • как следствие более высокая скорость работы и меньше потребление памяти (ядро отрабатывает за 2-4 мс и кушает около 1 МиБ памяти в пике, остальное зависит от разработчика конечного функционала)
  • не предполагает сборки из разнообразных компонентов — всё уже собрано и адекватно настроено
  • нет централизованного конфига маршрутов, каждый компонент хранит всё в себе
  • простота — благодаря более низкому уровню абстрактности кода порог входа значительно ниже
  • все части ядра подогнаны, при необходимости пропатчены, и гарантированно работают вместе, это не просто набор произвольных библиотек, а единое функциональное целое

В сравнении с CMS:

  • из коробки никакой специфической функциональности, только ядро и больше ничего
  • как следствие добавляется только необходимая функциональность
  • как следствие более высокая скорость работы и меньше потребление памяти
  • так же выше гибкость — настраивается и хакается буквально всё
  • практически не существует вида сайта, который нельзя сделать из-за архитектурных ограничений
  • поддержка вещей более характерных для фреймворков, например подхватывается composer, есть Restful API

Сложность, избыточность



Мне всегда не нравились файлы вида:

<?php
namespace Acme\DemoBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class AcmeDemoBundle extends Bundle
{
}

Это чуть меньше чем полностью бесполезный файл не несущий никакой полезной нагрузки, это шаблон, а шаблоны должны подразумеваться по умолчанию, если не менять шаблон — его не нужно и создавать.
Поэтому в CleverStyle CMS подобные шаблонные штуки не нужны, вы пишете код только тогда, когда он делает хоть что-то полезное.

Как пример — вам практически никогда не нужно прописывать вручную подключение CSS/JS/HTML файлов на страницах — можно в простом JSON указать на каких страницах они нужны — система сделает это автоматически, а можно не указывать — тогда файлы будут подключены на всех страницах сайта (что иногда тоже вполне себе вариант).

Хотите Hello, world! — прямо так и пишете в index.html, ложите файл в папку модуля, включаете модуль в админке, он готов к работе. Не нужно кучи вложенных папок, шаблонных контроллеров и прочего — просто файл с контентом.

Нет бесконечных конфигов — есть один маленький базовый с настройкой доступа к БД, хранилищу, кэшу, указан базовый часовой пояс, базовый язык сайта, и ключи которые используются для соли пароля и для шифрования — критически важные параметры, которые нужны для запуска ядра.
Параметры прописываются на этапе установки, большинство генерируется/определяется автоматически.
Все остальные возможные параметры настраивается в графическом интерфейсе и хранятся в БД.

Настройки компонентов тоже хранятся в БД, и очищаются при удалении компонента, для управлением конфигурацией компонента есть предельно простой внутренний API — параметры задаются как свойства объекта.

Маршруты тоже работают максимально просто, в общем виде выглядит так: api|admin/Module_name/level_1/level_2, при этом всё кроме Module_name необязательно и используется только когда нужно.
На каждом уровне маршрута есть ответственный файл, который отрабатывает свой уровень, но если обработка нужна только на следующем уровне — на текущем обаботку можно пропустить.
Сами уровни описываются одно- или двумерным массивом в формате JSON:

{
	"level_1" : [
		"sublevel_1",
		"sublevel_2"
	]
}

При открытии страницы admin/Module_name/level_1/sublevel_1 отработают следующие файлы при наличии:

  • admin/index.php
  • admin/level_1.php
  • admin/level_1/sublevel_1.php

Так же из соображений простоты и удобства выбирались и сторонние компоненты, например:

  • PHPMailer — единственный файл, в котором есть всё для отправки почты, для поддержки SMTP нужен ещё один файл
  • PHPT тесты — запускаются из одного файла, писать и читать тесты просто (не зря их используют в разработке самого PHP, и, например, в модифицированном виде в HHVM), в отличии от монстра PHPUnit

Функциональность, скорость




Из коробки система понимает что бывает несколько БД, они могут быть разными, у них бывают зеркала, умеет случайным образом балансировать запросы между зеркалами (можно отправлять запросы на запись на мастер, а чтение на зеркала). Аналогично поддерживается несколько хранилищ для статики.

Поддерживается многоязычность интерфейса и содержимого, ядро (и базовые компоненты, ниже) из коробки использует это везде где применимо.

Есть пользователи группы пользователей, разрешения, которые можно назначать как группам, так и на отдельным пользователям, поддерживаются связи между пользователями (простая система контактов).

Есть интерфейс отправки почты, в том числе с вложениями и прочими нужными возможностями.

Повсеместное кэширование — в подавляющем большинстве запросов ядро даже не соединяется с БД, так как кэшируется всё, что имеет смысл кэшировать.

На фронтенде подключены jQuery, UIkit, Polymer (+ WebComponents.js), они настроены работать вместе (это не всегда тривиально, учитывая веб-компоненты).
Веб-компоненты используются наравне с обычным CSS/JS кодом, система понимает HTML импорты, можно использовать Paper Elements и любые сторонние готовые компоненты с легкостью.

Зависимости между компонентами (обязательные и не очень) автоматически влияют на порядок включения CSS/JS/HTML файлов на странице, так что у вас всегда будет предсказуемый и правильный порядок инициализации файлов.

CSS/JS/HTML файлы минифицируются, объединяются, жмутся с помощью gzip в отдельные файлы, которые подключаются всё так же с учётом зависимостей, система делает всё сама, в том числе выставляет заголовки для правильного кеширования файлов браузером и/или CDN.

Все создаваемые файлы и записи в БД контролируются, таким образом производительность является контролируемой и предсказуемой. Это дает комфортное ощущение контроля за состоянием сайта.

Также генерируются правильные мета-тэги чтобы объяснить поисковым системам на каких языках по какому адресу ещё доступна эта страница (в многоязычной конфигурации), генерируются Open Graph мета-тэги.

Компоненты собираются в дистрибутивы через либо графический интерфейс, либо из командной строки, устанавливаются/обновляются из админки в графическом интерфейсе (ядро тоже можно ставить с командной строки).

На самом деле есть не только ядро




На самом деле да, для примера и для удобства создано несколько компонентов, которые либо несут полезную функциональность сами по себе, либо, что ещё более важно, легко интегрируются в другие компоненты.
Прямо сейчас готовы:

  • Blogs — блог (одно и многопользовательский), организация частично почерпнута из хабрахабра
  • Comments — комментарии, интегрируется в другие компоненты
  • Disqus — аналогично Comments, но с использованием одноименного сервиса, интегрируется так же как Comments, можно на выбор брать либо один, либо другой
  • Cron — простой менеджер crontab (обертка над консольными командами)
  • Deferred tasks — позволяет отложить выполнение задачи, ускоряя ответ сервера, выполняя задачу в фоне
  • Feedback — простая обратная связь
  • Photo gallery — фотогаллерея
  • fotorama.js — jQuery плагин слайд-шоу для фото и не только, интегрируется с другими компонентами
  • Plupload — HTML5 загрузчик файлов, интегрируется в другие компоненты, работает как с кликом, так и с перетаскиванием файлов на объект (Drag & Drop)
  • TinyMCE — визуальный HTML редактор, интегрируется в другие компоненты
  • OAuth2 — сервер OAuth2, позволяет, например, подключать к сайту мобильные приложения
  • HybridAuth — вход на сайт через множество разнообразных социальных сетей и прочих сервисов
  • Content — создание простых элементов контента с возможностью редактировать на месте, интегрируется с другими компонентами, может использоваться сам по себе
  • Static pages — возможность создавать простые статические страницы

Кроме стандартной темы оформления, которая используется в основном только для админки есть ещё две, также сторонние портировать проще простого, ведь тема оформления — простой HTML файл, в который подставляется контент и некоторые другие данные (есть два примера портирования в GitHub с пошаговыми коммитами от исходного шаблона, до состояния когда он является темой оформления CleverStyle CMS).

Разное





Ядро CleverStyle CMS всего 2 МиБ и состоит примерно с 280 файлов (это уже включая все сторонние библиотеки), имеет всё необходимое для разработки подавляющего большинства всевозможных сайтов размером от визиток до масштабируемых на несколько серверов.

Все инструменты готовы к использованию прямо после установки (состоящей из одного шага), и не нуждаются в обязательной настройке, но поддаются перенастройке при надобности.

Архитектура спроектирована с нуля, несколько менялась со временем, учитывая опыт практического использования в продакшене, и устаканилась в таком виде, в котором есть сейчас.
В ядре используются как готовые сторонние библиотеки так и специально написанные, некоторые были написаны специально для CleverStyle CMS и потом отделились в самостоятельные проекты.

Код доступен на GitHub под MIT лицензией: https://github.com/nazar-pc/CleverStyle-CMS

Несмотря на то, что система должна рассматриваться скорее как монолит — многие части либо сразу, либо с небольшим усилием можно оторвать и использовать отдельно — например, минификация и объединение CSS/HTMLфайлов, реализация псевдо-файловой системы в кэше (по сути поддержка тэгов) для APC и Memcached, да и ещё много чего, код под MIT лицензией, можно использовать.

Есть wiki с описанием устройства и взаимодействия различных частей системы: https://github.com/nazar-pc/CleverStyle-CMS/wiki

На базе движка работает несколько сайтов, есть мобильные приложения, так что функционал живой и рабочий, используется в боевых условиях.

Как попробовать




Демка с публично доступным сайтом плохо поддерживается — то пароль кто-то изменит, то настроит что-то, да и сломать с полным админским доступом при желании не сложно.
Благодаря тому, что последние версии поддерживают сборку и установку в режиме командной строки стало возможным приготовить образ для Docker с автоматически обновляемой и всегда последней git версией системы.
Запускается так:

docker run --rm -p 8888:8888 nazarpc/cleverstyle-cms

После этого можно открывать http://localhost:8888 и смотреть (логин admin, пароль 1111), все компоненты изначально отключены, но доступны в админке.
--rm удалит контейнер после остановки (остановить можно с помощью Ctrl+C).