Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. CMS

Создаем CMS: nodePress

by
Difficulty:IntermediateLength:LongLanguages:

Russian (Pусский) translation by AlexBioJS (you can also view the original English article)

Вы уже успешно создали CMS (* content management system – система управления содержимым; ПО для организации совместных работ по созданию документов и другого контента. Здесь и далее примеч. пер.), работающую на основе плоской файловой системы (* система организации файлов, при которой они не могут иметь одинаковых имен, если даже находятся в разных каталогах), при помощи Go. Следующий шаг – реализовать то же при помощи Node.js. Я покажу вам, как загрузить библиотеки, создать и запустить сервер.

В этой CMS мы будем использовать ту структуру данных сайта, которая была показана в первом руководстве, «Building a CMS: Structure and Styling». Поэтому скачайте и распакуйте архив с этой базовой структурой в пустую директорию.

Устанавливаем Node и библиотеки для нее:

Простейший способ установить Node.js на Mac – при помощи Homebrew (* наиболее популярный пакетный менеджер для Mac). Если Homebrew у вас еще не установлен, то можете посмотреть, как это сделать, в руководстве «Homebrew Demystified: OS X’s Ultimate Package Manager».

Для установки Node.js при помощи Homebrew выполните следующую команду в командной строке:

После ее выполнения на вашем Mac станут доступны все команды с node и npm. Для установки Node.js на все остальные платформы придерживайтесь инструкций, приведенных на веб-сайте Node.js.

Будьте осторожны: многие пакетные менеджеры в данный момент устанавливают Node.js версии 0.10. В этом руководстве предполагается, что вы используете версию 5.3 или более новую. Вы можете проверить, какую версию вы используете при помощи:

При помощи команды с node запускается интерпретатор JavaScript. При помощи команды с npm в дело вступает пакетный менеджер Node.js для установки библиотек, создания новых проектов и запуска скриптов для проекта. На Envato Tuts+ имеется множество замечательных руководств и курсов по Node.js и npm.

Для установки библиотек для сервера вам необходимо выполнить следующие команды в программе Terminal.app или iTerm.app:

Express – фреймворк для разработки веб-приложений. Он подобен библиотеке goWeb в Go. Handlebars – шаблонизатор (* программное обеспечение для комбинирования шаблонов с моделью данных для получения конечных документов) для создания страниц. Moment – библиотека для работы с датами. Marked – отличный конвертер Markdown в HTML для JavaScript. Jade – уровень абстракции HTML для более простого создания HTML-страниц. Morgan – библиотека промежуточного программного обеспечения для Express, при помощи которой генерируются лог-файлы (* запись в журнале регистрации событий, фиксирующая действие и событие, произошедшее в компьютерной системе) стандарта Apache (* Common Log Format – общепринятый формат лог-файлов).

Альтернативный вариант установки необходимых библиотек – скачать исходные файлы для этого руководства. После скачивания архива и его распаковки выполните следующую команду в главной папке проекта:

За счет нее будет установлено все, что необходимо для создания рассматриваемого тут проекта.

nodePress.js

Теперь мы можем приступить к созданию сервера. В корневой папке проекта создайте файл под названием nodePress.js, откройте его в своем любимом редакторе и начинайте добавлять туда следующий код. Я буду объяснять код по мере его добавления в файл.

Код начинается с подключения всех необходимых для реализации сервера библиотек. Библиотеки, для которых не указаны комментарии с веб-адресами, поставляются в составе самой платформы Node.js.

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

Переменная parts – хэш (* коллекция пар ключ-значение, причем ключом является строка), содержащий все части веб-страницы. Ее контент используется при создании каждой страницы. Контент этой переменной начинается с содержимого файла server.json, что находится в корневой паке сервера.

Затем я использую информацию из файла server.json для создания полных путей к папкам styles и layouts, используемых для нашего сайта.

Далее в качестве значений трех переменных (siteCSS, siteScripts и mainPage) задается null. В этих глобальных переменных будет содержаться контент всех файлов CSS, JavaScript и главной страницы. Эти три элемента запрашиваются наиболее часто на всех серверах. Поэтому за счет размещения их в памяти мы ускоряем работу сайта. Если значением свойства Cache в файле server.json является false, то эти элементы считываются заново при каждом запросе.

В этом коде настраивается библиотека Marked для получения HTML из Markdown. Главным образом, тут я активирую поддержку таблиц и «умных» списков (* smartList; список с поддержкой фильтров).

Затем в переменную parts добавляется контент папок styles и layouts. Контент каждого файла папки parts, что располагается в папке site также загружается в глобальную переменную parts. Имя файла без расширения – имя, используемое для сохранения контента файла. Эти имена заменяются набором инструкций в макросах (* (от греческого makros - большой, длинный) последовательность команд и/или нажатий клавиш, записанная макрорегистратором под уникальным именем. Эта последовательность затем может быть исполнена путём указания данного имени) Handlebars.

В следующей части кода идет определение хелперов Handlebars, которые будем использовать в веб-сервере: save, date и cdate. В хелпере save предусматривается создание переменных на странице. Эта версия хелпера поддерживает версию CMS goPress, в которой в параметре одновременно присутствуют имя и значение вместе, разделенные при помощи “|”. Также можно задать используемые в хелпере значения при помощи двух параметров. Например:

В обоих случаях получается одинаковый результат. Я предпочитаю использовать второй подход, однако в библиотеке Handlebars, используемой для Go не предусматривается передача более одного параметра.

При помощи хелперов date и cdate форматируется текущее значение даты (date) или указанное (cdate) в соответствии с правилами форматирования, указанными в библиотеке moment.js. При использовании хелпера cdate предполагается, что подлежащая форматированию дата будет передана в качестве первого параметра в формате ISO 8601 (* международный стандарт, выданный организацией ISO (International Organization for Standardization – Международная организация по стандартизации), который описывает форматы дат и времени и дает рекомендации для его использования в международном контексте).

Далее в коде создается образец Express для настройки собственно веб-сервера. При помощи функции nodePress.use() происходит настройка промежуточного программного обеспечения. Промежуточное программное обеспечение – любой код, который выполняется при каждом запросе к серверу. Тут я настраиваю библиотеку Morgan.js для получения необходимого формата записей в журнале регистрации событий.

В этом разделе кода определяются все необходимые для реализации сервера маршруты. Во всех маршрутах выполняется функция setBasicHeader() для установки необходимых значений заголовков. В результате любых запросов на получение страниц будет вызвана функция page(), в то время как в результате любых запросов на получение постов будет вызвана функция post().

Значение по умолчанию для заголовка Content-Type – HTML. Поэтому при отправлении CSS, JavaScript и изображений мы специально задаем для Content-Type соответственное значение.

Также вы можете определять маршруты при помощи методов REST (* Representational State Transfer – передача репрезентативного состояния; способ обеспечения способности к взаимодействию компьютерных систем в Интернете) put, delete и post. В этом небольшом сервере используется только метод get.

Нам осталось теперь, перед определением различных используемых в коде функций, только запустить сервер. В файле server.json содержится DNS-имя (у нас localhost) и порт для сервера. После парсинга (* разбиение строки текста на составные части) в функции listen() используется номер порта для запуска сервера. После открытия порта сервера за счет скрипта в консоль выводится адрес и порт сервера.

Первая функция, которую будем определять, – setBasicHeader(). При помощи этой функции устанавливается значение специального заголовка ответа для сообщения браузеру о необходимости кэширования страницы на один месяц. Также благодаря ней браузеру сообщается, что сервер – это сервер nodePress. Если бы вы хотели добавить еще какие-либо стандартные заголовки, то добавили бы их при помощи функции response.append() .

В функции page() шаблон разметки страницы и адрес страницы на сервере передаются в функцию processPage().

Функция post() подобна функции page(), за исключением того, что при создании поста используется больше информации. В создаваемых в этой серии руководств серверах пост содержит тип, категорию и собственно пост. Типом поста является либо blogs, либо news. Категория – flatcms. Поскольку ими являются имена директорий, то вы можете давать им любые имена. Просто подберите имя так, чтобы оно совпадало с тем, что используется в вашей файловой системе.

Функция processPage() принимает макет и путь к необходимому для отображения контенту страницы. Код функции начинается с создания локальной копии глобальной переменной parts и добавления ключа, используемого для размещения “контента”, значением которого является результат выполнения функции figurePage(). Далее в качестве значения PageName задается имя страницы.

Далее происходит компиляция контента страницы в шаблон с разметкой при помощи Handlebars. Затем за счет функции processShortCodes() весь сокращенный код на странице будет преобразован в полный. После этого шаблонизатор Handlebars прогоняет код через себя еще раз. И затем браузер получает результат.

Функция processShortCodes() принимает контент веб-страницы в качестве строки и производит поиск всех частей кода в сокращенным виде. Сокращенный код – это блок кода, подобный тегам HTML. Примером мог бы послужить:

В этом коде имеется сокращенный код для box вокруг параграфа HTML. Там, где в HTML используется < и >, в сокращенном коде используется -[ и ]-. После имени может при необходимости добавляться строка с аргументами для сокращенного кода.

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

В этой части идет json-структура сокращенного кода, в которой определяются имена сокращенного кода со связанными с ними функциями. Все функции для сокращенного кода принимают два параметра: args и inside. аrgs – все, что идет после имени и пробела до конца тега. inside – все, что располагается между открывающим и закрывающим тегами сокращенного кода. Это базовые функции, однако вы можете создать сокращенный код для выполнения чего-угодно на JavaScript, что приходит вам в голову.

Функция figurePage() получает полный путь на страницу на сервере. Затем в этой функции проверяется формат страницы (HTML, Markdown или Jade) на основании расширения. Я по-прежнему использую .amber для кода на Jade, поскольку я использовал библиотеку Аmber при создании сервера goPress. Весь контент на Markdown и Jade транслируется в HTML перед его передачей рутинной функции (* return). Поскольку процессор Markdown преобразует все кавычки в &quot;, я преобразую их обратно перед возвращением результата.

Функция fileExists() – замена для функции fs.exists(), которая была частью библиотеки fs Node.js (* до версии 1.0.0). В ней используется функция fs.statSync(), чтобы попытаться получить статус файла. В случае ошибки функция возвращает false. В ином случае возвращается true.

Переходим к последней функции – MergeRecursive(). В ней происходит копирование второго переданного объекта в первый. Я ее использую для копирования содержимого основной глобальной переменной parts в локальную копию перед добавлением частей, присущих различным страницам.

Запускаем сервер локально:

После сохранения файла вы можете запустить сервер при помощи:

В качестве альтернативного варианта вы можете использовать указанный в файле package.json скрипт, запускаемый при помощи команды npm. Запуск скриптов при помощи npm выполняется следующим образом:

При помощи этой команды будет выполнен скрипт start, указанный в файле package.json.

nodePress Server Main Page
Главная страница сервера nodePress

Перейдите в вашем браузере по http://localhost:8080 и вы увидите страницу, показанную выше. Вы, должно быть, заметили, что я добавил дополнительный код для тестирования сайта на главную страницу. С внесенными на страницы изменениями вы можете ознакомиться в присоединенных файлах. Это, по большей части, просто некоторые небольшие поправки, внесенные для более полного тестирования функциональных возможностей и подгонки кода под требования различных библиотек. Наиболее значительное различие состоит в том, что в библиотеке Jade не используется $ при наименования переменных, а в Amber используется.

Заключение

Теперь у вас есть идентичные CMS, работающие на основе плоской файловой системы, реализованные при помощи Gо и Node.js. Мы воспользовались только базовыми возможностями этой платформы. Поэкспериментируйте и попробуйте что-нибудь новое. Это самое интересное при создании собственного сервера.

Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.