Четыре года — это в IT уже долгострой. Именно столько, и даже чуть больше времени мне понадобилось чтобы довести CleverStyle CMS до версии 1.0, до состояния когда архитектура устаканилась, имеется достаточная функциональность и целостность системы как таковой, все найденные баги исправлены, и основные сценарии работают без проблем.
Получилось создать что-то среднее между фрейворком и, собственно, CMS, как раз то, что нужно для разработчика, и хочу поделиться этим с сообществом.
Уверен, многим не хватало именно такого решения, это подтверждается многочисленными вопросами на том же Тостере и долгими ветками комментариев под ними.
Обязательно нужно объяснить почему
Сложность, избыточность, гибкость, функциональность и скорость.
Я не нашел решения, которое имело бы удовлетворительный для меня баланс этих параметров (безопасность тоже, но это очевидно и подразумевается само собой изначально).
CleverStyle CMS — это не CMS в привычном смысле, это CMF, выше фреймворка по уровню архитектуры но ниже и гибче CMS.
В связи с таким позиционированием получилось очень удобное решение в первую очередь для разработки уникального функционала, так как есть большинство необходимых инструментов, за которыми не нужно далеко идти, не нужно настраивать, а можно сразу использовать и получать результат.
Отличия в сравнении с фреймворком:
- существенно меньше слоев абстракции
- как следствие проще и прозрачнее структура
- как следствие более высокая скорость работы и меньше потребление памяти (ядро отрабатывает за 2-4 мс и кушает около 1 МиБ памяти в пике, остальное зависит от разработчика конечного функционала)
- не предполагает сборки из разнообразных компонентов — всё уже собрано и адекватно настроено
- нет централизованного конфига маршрутов, каждый компонент хранит всё в себе
- простота — благодаря более низкому уровню абстрактности кода порог входа значительно ниже
- все части ядра подогнаны, при необходимости пропатчены, и гарантированно работают вместе, это не просто набор произвольных библиотек, а единое функциональное целое
В сравнении с CMS:
- из коробки никакой специфической функциональности, только ядро и больше ничего
- как следствие добавляется только необходимая функциональность
- как следствие более высокая скорость работы и меньше потребление памяти
- так же выше гибкость — настраивается и хакается буквально всё
- практически не существует вида сайта, который нельзя сделать из-за архитектурных ограничений
- поддержка вещей более характерных для фреймворков, например подхватывается composer, есть Restful API
Сложность, избыточность
Мне всегда не нравились файлы вида:
<?php
namespace AcmeDemoBundle;
use SymfonyComponentHttpKernelBundleBundle;
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).
Автор: nazarpc