- PVSM.RU - https://www.pvsm.ru -
часть 1 [1]
В первой части шла речь о «проверенных временем» решениях, утянутых домовитыми лапами на ноду. Теперь немного лисапедов и пара мыслей вслух.
Адрес — github.com/nodeca/puncher [2]
Если вам не безразлична производительность, ее желательно контролировать во время разработки. Один из самых простых способов — расставить по коду таймстампы. Это ни в коем случае не «единственный» и не «самый лучший» способ. Просто он часто удобен на самом раннем этапе, когда пишется код и делается ревью — не нужно заниматься сбором статистики, и вообще «далеко ходить». Достаточно вывести прямо внизу страницы таймлайн, и сразу будет видно, что не так. Естественно, потом полезно в любом случае смотреть логи медленных запросов и собирать прочую статистику профайлером. Но проблемных мест останется на порядок меньше. И выясните вы это сразу на ревью, а не когда-нибудь потом, когда
Сам пример можно посмотреть тут, отмотав страницу в самый конец: dev.nodeca.com/ [4]. Данные генерируются самодельным модулем puncher. Он позволяет очень легко расставить по коду вложенные интервалы. Это не бенчмарк. Это именно инструмент, который позволяет обнаружить проблемы на самом раннем этапе. Ну и сделать некоторые выводы о том, чего вообще ожидать. При некоторой ловкости, достаточно 1-2 таймлайнов, чтобы увидеть профуканные индексы и медленный код.
Библиотека простая, но не совсем волшебная :). Пересекающиеся интервалы для «параллельных» вызовов, она не просекает. Но, как говорят наши друзья из яблочной компании, «вам этого не нужно» :). У нас сначала были параллельные вызовы, потом я посмотрел таймлайн — увидел нулевую экономию, и выстроил все водопадом, чтобы не возиться.
Адрес — github.com/nodeca/babelfish [5]
Это второй после пунчера велосипед — попытка радикально упростить интернационализацию. Конечно, я в курсе про gettext(). Но мысль о клепании пучка фраз на каждую плюрализацию навевала тоску и вгоняла в депрессию. Захотелось указывать плюральные формы сразу в одной строке, и вообще, клепать фразы легким движением бровей. Возможно, это слегка отдает кодингом, но не выходит за рамки добра и зла. Главные критерии — простота набивки и перевода. Вот реальный пример: github.com/nodeca/nodeca.forum/blob/master/config/locales/general.en-US.yml [6]. С моей точки зрения, такой файл вполне реально отдавать переводчику. Ну и программистов тоже не напрягает.
Естественно, библиотека рассчитана на работу как на сервере так и на клиенте. Правила плюрализации сделаны и оттестированы для всех языков, найденных в юникодном стандарте.
Адрес — github.com/fontello/fontello [7]
Сайт — fontello.com/ [8]
Это симбиоз детской мечты и суровой реальности :). Не буду рассказывать про иконочные шрифты, потому что уже касался этой темы в других статьях. Просто отмечу, что по мере работы над нодекой, возникла побочная идея «сделать классную хрень». Ну а так как в сутках лишь 24 часа, то пришлось придумывать для самого себя отмазки, чтобы отвлечься от основного проекта. В итоге фонтелло используется в качестве песочницы, для проверки всяких завихрений
Из последнего — доделали инлайновое редактирование имен глифов, и привели генерируемые файлы к формату, удобному для скидывания в репозитори. Когда надо будет расширить фонт — просто импортируем конфиг и продолжаем работу. Для тех, кто предпочитает сам задавать @font-face, генерируются файлы, состоящие только из кодов символов. В общем, процесс оптимизирован под разработчиков, любящих автоматизацию и гитхаб.
Кстати, на днях со мной связался Daniel Bruce, автор Entypo. Ожидается большое обновление.
dev.nodeca.com/ [4]
Это штука, с которой все началось, и от которой приходилось все время отвлекаться :). Работа еще не закончена, но мы уже перестали «активно развивать нодовские библиотеки» — на данный момент архитектура почти стабилизировалась. Как обычно, тырили с миру по нитке творчески переосмысливали удачные решения, где возможно, и сочиняли свое, где позволял опыт. Наверное, можно сказать, что мы сделали свой «фреймворк». Просто времени его продвигать особо нет. Но кого интересуют подходы — можно посмотреть текущую документацию, сделанную для внутренних нужд: github.com/nodeca/nodeca/tree/master/docs/nodeca-technical [9]. Так как проект еще не готов, и код местами «прототипного» качества, то просто расскажу о некоторых проверенных вещах и практических выводах.
Отсюда мы взяли древовидную идею адресации серверных методов, (вместо controller/action). Изначально хотелось использовать SS напрямую, но там не были проработаны моменты с серверным рендерингом, разбивка на несколько подпроектов и т.п. В общем, сам по себе socketstream интересен, и почерпнуть там было чего. Но не целиком :)
Из довольно интересной концепции была передача данных по вебсокетам. С виду это выглядело красивым, но на практике оказалось большой жопой, что данные не пакуются. То есть, JSON для генерации на клиенте занимал в несколько раз больше (!) чем целиком отрендеренный HTML, пожатый в gzip. Можно конечно было подсуетиться с ручной перепаковкой, но это отдавало серьезным маразмом. К тому же, вебсокеты расчитаны не на бинарные данные, а на utf-8, поэтому внутри все заворачивается в base64, и мы пролетаем на 30% по сравнению с аяксом.
Второй проблемой с вебсокетами стало несовершенство библиотек. Наблюдались странные «провисания», что абсолютно неприемлимо при кликах на элементах интерфейса. Это все, конечно, не высосано из пальца, а было обнарушено на фонтелле и текущей нодековской тдемке. Наверное, если упереться рогом в землю и потратить прилично времени, можно было бы все свести к боевой ничьей. Но смысл? В итоге, для обычных RPC-запросов откатили все на аякс, а FAYE/Socket.io отложили именно для подписок, где размер данных и задержки не особо актуальны (или по крайней мере не так заметны).
Из удачно стырепозаимствованных концепций оказались рельсовские before/after фильтры. С учетом специфики — рекурсивности (для дерева) и коллбеков. В коде выглядит вот так: github.com/nodeca/nodeca.forum/blob/master/server/forum/thread.js#L57 [10]. Привычная классика, но в нодовском стиле.
Этой ODM нода несомненно может гордиться. Отличная библиотека. Но есть нюанс. На выборке кастинг документов работает ОООЧЕНЬ МЕЕЕЕДЛЕННО. К счастью, в версии 3.0 добавили опцию {lean: true}, которая отключает нафик всю магию (и удобства) и выдает данные из драйвера как есть.
В итоге получается так:
Профит! Раньше для «быстрых» запросов надо было брать другие библиотеки или вручную лезть к монговскому драйверу. Теперь проблем нет.
(*) Кто успел проапгрейдиться на могу 2.2 — монгуз поддерживает агрегацию, и там сразу выдает некастованные объекты.
Из важных замечаний — не буду клясться на 100%, но сложилось впечатление, что создание больших объектов в javascript — не совсем бесплатная операция. Фильтрация полей во время запроса дает довольно большой прирост скорости выборки. При том что в консоли монги время не менялось. Тормоза спрятались где-то в передачи данных из монги в v8. Я был бы очень признателен, если бы кто-нибудь прояснил этот момент.
Это одна из самых крутых фишек ноды. Если она вам нужна :). Будут говорить про асинхронность и скорость — не верьте. В других платформах есть сравнимые решения. Но без проблем заколбасить универсальные разухабистые шаблоны (с хелперами и т.п.) и на сервере и на клиенте можно только при использовании ноды. Если вам действительно нужна такая фишка — он ноды может быть смысл. Если нет — возможно, вам будет быстрее и интереснее писать на другом языке. Я не сторонник маниакального сования ноды везде где можно.
В общем, это была лирика, а теперь возвращяемся к рендерингу и идем за примером опять сюда: dev.nodeca.com/ [4]. Если в современом браузере потыкать по ссылкам и посмотреть вниз, то вы обнаружите, что в таймлайне пропала операция рендеринга. Это та самая военная хитрость — рендеринг идет на клиенте, а location подкручивается через history api. Профит заключается в том, что не надо отдельно думать над индексацией, лепить под гугла шибанговский клозет, и горевать, что это не работает в яндексе. Ну и конечно же, программисту теперь вообще не надо думать, где именно отрендерится его шаблон.
Насчет скорости шаблонизации стоит поговорить отдельно. Лично я предпочитаю Jade. В стоковом режиме он не самый быстрый. Но есть две волшебных опции, которые все меняют :)
{ compileDebug: false, self: true }
Первая отключает генерацию отладочной информации. Вторая генерирует код без `with` — но вам прийдется добавлять `self.` ко всем именам переменных, переданным в шаблон. Вполне приемлимая цена. На страницах нодеки выигрыш по скорости оказался ~ в полтора-два раза (изначально таймлайн показывал, что рендеринг выедал 50-70% от запроса). Так что результат вполне полезный. compileDebug еще как-то можно найти в документации (если догадаетесь, что надо искать), а вот про self — уже не факт. Поэтому считаю не зазорным поделиться «находкой».
Для тех, кому интересно, могу еще предложить ссылку на «тесты» jsperf.com/template-without-precompile/8 [11]. Слово тесты взял в кавычки, потому что в реальной жизни результат немного другой :). Сколько бы миллионов попугаев ни показывали пузомерки, в шаблонах все равно останутся вызовы i18n, конверторов дат и прочих хелперов, которые радикально изменят результат. Поэтому советую проверять чем-то вроде пунчера на реальных страницах.
Пока всё. Надеюсь, это будет кому-то полезно :). Когда появятся новости про нодеку — напишу еще раз.
PS. Если кто-нибудь захочет поучаствовать в разработке нодеки — есть пара вакансий.
Автор: Vitaly
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/node-js/14161
Ссылки в тексте:
[1] часть 1: http://habrahabr.ru/post/150496/
[2] github.com/nodeca/puncher: https://github.com/nodeca/puncher
[3] мозг: http://www.braintools.ru
[4] dev.nodeca.com/: http://dev.nodeca.com/
[5] github.com/nodeca/babelfish: https://github.com/nodeca/babelfish
[6] github.com/nodeca/nodeca.forum/blob/master/config/locales/general.en-US.yml: https://github.com/nodeca/nodeca.forum/blob/master/config/locales/general.en-US.yml
[7] github.com/fontello/fontello: https://github.com/fontello/fontello
[8] fontello.com/: http://fontello.com/
[9] github.com/nodeca/nodeca/tree/master/docs/nodeca-technical: https://github.com/nodeca/nodeca/tree/master/docs/nodeca-technical
[10] github.com/nodeca/nodeca.forum/blob/master/server/forum/thread.js#L57: https://github.com/nodeca/nodeca.forum/blob/master/server/forum/thread.js#L57
[11] jsperf.com/template-without-precompile/8: http://jsperf.com/template-without-precompile/8
Нажмите здесь для печати.