- PVSM.RU - https://www.pvsm.ru -

О разработке на node.js … Часть 1

Мы уже некоторое время пишем развесистую клюкву на node.js. И хоть будующее наше туманно, образовались всякие полезные штуки и наблюдения, которыми захотелось поделиться :). Так получилось, что есть проект, где тонна скриптов на старом добром php достигла своего предела. Ну и конечно захотелось «все взять и переписать нормально», как обычно.

Рыбу того, к чему стремимся, можно тыкать мышкой и палочкой здесь: dev.nodeca.com/ [1], а сам код выложен на гитхабе [2].

Поскольку серьезные прессинги в виде денег и сроков отсутствовали, то можно было полностью погрузиться в программирование, а не «гнать продукт». Хотелось взять что-то эдакое, с подвывертом, чтобы размять мозг [3]. На полном серьезе я рассматривал node.js / ruby / python. Не могу сказать, что составил миллион метрик и открыл волшебную формулу, которая подсказала превосходство node.js. Скорее, захотелось поковыряться с «прозрачным» рендерингом шаблонов на сервере и клиенте. Ну и чем-то приглянулась заточка исключительно на асинхронность, хотя сам способ (коллбеки) может вызывать нарекания.

Если вы начнете делать на ноде что-то сложнее школьной лабораторки, то быстро обнаружите, что «проект молодой». Библиотеки крайне сегментированы. Наряду с прекрасными вещами, вроде jade, stylus, mongoose и т. п., вы наткнетесь на полное отсутствие вещей, которые давно реализованы в других языках. А якобы аналоги будут на уровне «напевал рабинович». В общем, вместо разработки своего софта, пришлось «вносить мощный вклад в опенсорц». Это первое предупреждение для тех, кто всерьез думает над выбором ноды для бизнес-проекта — адекватно оценивайте наличие инструментов и их качество. Конечно, можно было по-быстрому наколхозить костылей. Но в нашем случае не было жесткой ориентации на финальный продукт. Поэтому время от времени возникали рывки вбок, о которых я расскажу ниже.

ndoc (генератор документации)

Адрес: github.com/nodeca/ndoc [4]
Демо: nodeca.github.com/ndoc/tests/prototype/ [5]

Когда в проекте много кода — без документации совсем никак. И в первую очередь это касается библиотек. Вы будете смеяться, но под ноду НЕ БЫЛО генераторов документации по API. Почему-то большинство клепало так называемые «annotaded sources», выгоду от которых я совершенно не понимаю.

Вообще в мире много разных документаторов. Мы за основу взяли рубиновый pdoc [6] — синтаксис понравился. Сначала использовали оригинал, а потом сделали нодовский порт. Одной из подзадач было освоить генераторы парсеров. В ноде это jison [7] и pegjs [8].

Конечно, добавили всяческие улучшения:

  • В отличие от оригинала, который является библиотекой, мы сделали сразу CLI-утилиту.
  • Попутно поправили неточности в спецификации на pdoc (спасибо Tobias за помощь).
  • Переделали внешний вид, сменили формат на «одностраничный», а верстку на html5.
  • Добавили файл конфигурации, как у js-hint и travis.

В качестве «proof of concept» можно собрать документацию на prototype, под который изначально разрабатывался pdoc. Она включена в проект в качестве тестового примера.

В общем, если понравится — пользуйтесь на здоровье. При желании можно добавить дополнительные генераторы форматов, поддержку кофескрипта и т. п. Архитектура позволяет.

argrapse (парсер командной строки)

Адрес: github.com/nodeca/argparse [9]

По мере разрастания проекта обнаружилось, что имевшиеся нодовские парсеры откровенно «слабоваты». Это типичная ситуация с многими нодовскими библиотеками — код делается под небольшую локальную задачу. Кому-то еще подойдет, но об универсальности говорить трудно.

Способ решения проблемы простой — смотрим где плохо лежит ищем качественную реализацию в других языках и делаем порт. Остановились на питоновском argparse docs.python.org/dev/library/argparse.html [10]. Портировали 1:1, кроме пары мелочей, на которые не хватило времени. В итоге даже не стали делать на него документацию — просто сослались на оригинал.

mincer (менеджер ассетов, порт sprockets)

Адрес: github.com/nodeca/mincer [11]

Это порт очень крутой вундервафли известного менеджера ассетов sprockets [12]. Тоже сделано по принципу «проще один раз портировать нормальную вещь, чем постоянно рихтовать свой самокат». Мы люди не гордые, на авторство идей не претендуем. Зато нам теперь хорошо. И тем, кто делает сложные проекты, теперь тоже будет легче. Еще раз подчеркиваю, это полнофункциональный порт, а не «сочинение на тему», вроде snockets.

Вот примерный список возможностей, если кто не сталкивался:

  • Объединение JS/CSS для оптимизации загрузки страниц
    • легкое встраивание оптимизаторов/углификаторов.
    • встроенный шаблонизатор, например для вставки новера версии в сгенерированную статику
  • Поддержка основных современных движков (Jade / Stylus / Less / Coffescript / HamlCS / EJS)
  • Универсальные хелперы — можно задать хелпер 1 раз, и он автоматически станет доступен во всех используемых движках.
  • Генерация уникальных путей, для правильной работы кеша (эти пути потом задаются через хелперы). Т.к. Пути содержат CRC файла, то
  • Встроенный быстрый сервер статики. Так как мы делаем статические слепки ассетов, то можно сразу загрузить все в память, вычислить gzip-ованные версии, и раздавать наружу данные прямо из буферов. Это не так идеально, как nginx, но весьма быстро.
  • Javascript Templates — можно из файлов, разложенных по директориям, сгенерировать «дерево», готовое к загрузке на клиента.

Честно предупреждаю, библиотека не для новичков. Но как только сложность проекта возрастает — mincer окупается существенным упрощением разработки и поддержки. Например, мы используем Stylus, но нам надо прицепить Twitter Bootstrap на Less, и обеспечить легкий апгрейд, когда выйдет новая версия. Получается как-то так: github.com/fontello/fontello/blob/master/assets/stylesheets/app.styl [13]. Ну и конечно правильное кеширование, с поддержкой «старых версий» файлов, тоже очень облегчает жизнь.

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

js-yaml (парсер YAML, порт PyYaml)

Адрес — github.com/nodeca/js-yaml [14]
Демо — nodeca.github.com/js-yaml/ [15]

Это, как говорится, наша «радость и боль». В ноде почему-то принято описывать структуры прямо в json. Соглашусь, для простых проектов, где конфигурационных данных мало, это довольно мило. Но когда объемы вырастают, то json начинает очень напрягать. В качестве «человеко-читаемого» формата давно придуман YAML www.yaml.org/ [16]. Там есть весьма нетривиальные навороты (которые мало кому нужны), но суть остается прежней — наклепать 10 страниц структур на ямле будет намного быстрее, чем на джейсоне. Ну и количество ошибок на километр кода будет меньше на порядок. Из очевидных бонусов — можно оставлять комментарии. Так что если у вас нет отступофобии, вам скорее всего понравится.

Сначала мы пробовали использовать уже готовые парсеры. Но в очередной раз «подорвавшись на мине», решили сделать порт PyYaml, чтобы иметь предсказуемое качество кода. Огромную помощь оказали авторы стандарта своими консультациями. В том числе, как адаптировать спецификации под особенности javascript.

Теперь наши конфиги выглядят как-то так: github.com/fontello/fontello/blob/master/config/router.yml [17]

Продолжение следует.

PS. Если есть люди, готовые выделить ресурсы на доведение описанных библиотек до «идеала» — дайте знать. С кодом проблем нет, но есть подозрение, что документацию и примеры стоит улучшить.

Автор: Vitaly


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/node-js/14060

Ссылки в тексте:

[1] dev.nodeca.com/: http://dev.nodeca.com/

[2] на гитхабе: https://github.com/nodeca/

[3] мозг: http://www.braintools.ru

[4] github.com/nodeca/ndoc: https://github.com/nodeca/ndoc

[5] nodeca.github.com/ndoc/tests/prototype/: http://nodeca.github.com/ndoc/tests/prototype/

[6] pdoc: https://github.com/tobie/pdoc

[7] jison: https://github.com/zaach/jison

[8] pegjs: https://github.com/dmajda/pegjs

[9] github.com/nodeca/argparse: https://github.com/nodeca/argparse

[10] docs.python.org/dev/library/argparse.html: http://docs.python.org/dev/library/argparse.html

[11] github.com/nodeca/mincer: https://github.com/nodeca/mincer

[12] sprockets: https://github.com/sstephenson/sprockets

[13] github.com/fontello/fontello/blob/master/assets/stylesheets/app.styl: https://github.com/fontello/fontello/blob/master/assets/stylesheets/app.styl

[14] github.com/nodeca/js-yaml: https://github.com/nodeca/js-yaml

[15] nodeca.github.com/js-yaml/: http://nodeca.github.com/js-yaml/

[16] www.yaml.org/: http://www.yaml.org/

[17] github.com/fontello/fontello/blob/master/config/router.yml: https://github.com/fontello/fontello/blob/master/config/router.yml