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

в 5:48, , рубрики: node.js, охотничьи байки, метки: ,

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Это порт очень крутой вундервафли известного менеджера ассетов sprockets. Тоже сделано по принципу «проще один раз портировать нормальную вещь, чем постоянно рихтовать свой самокат». Мы люди не гордые, на авторство идей не претендуем. Зато нам теперь хорошо. И тем, кто делает сложные проекты, теперь тоже будет легче. Еще раз подчеркиваю, это полнофункциональный порт, а не «сочинение на тему», вроде 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. Ну и конечно правильное кеширование, с поддержкой «старых версий» файлов, тоже очень облегчает жизнь.

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

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

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

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

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

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

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

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

Автор: Vitaly

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js