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

Thinking Reactively. Meteor JS

Если вы еще не слышали про meteor, значит вы вообще не следите за миром JavaScript, не интересуетесь вебом и непонятно каким образом сюда попали.
Пусть так.

Thinking Reactively. Meteor JS

Вступительное слово

Meteor — это один из самых необычных и эксперементальных фрэймворков для js за долгое время. Те, кто говорит, что это не MVC-фрэймворк, безусловно правы.

Один из 7 принципов, которые авторы выделяют на странице документации [1]: «Meteor is open source and integrates, rather than replaces, existing open source tools and frameworks». Этим самым они намекают на то, что не пытаются решать задачи, которые уже давно решены. Этим и тем, что одним из, так называемых «Smart Packages», которые уже интегрированы в meteor, является backbone [2].

Главное отличие meteor в том, что он не пытается структурировать ваш код, как большинство существующих фрэймворков, он пытается внушить вам определенный образ мышления [3] при разработке.

Reactivity

За этим словом скрывается основная идея подхода. Исторически сложилось, что традиционный для JavaScript подход — ассинхронный. Несмотря на то, что ничего сложного тут нет, иногда возникают проблемы в отладке. Иногда люди не могут понять, где код исполняется асинхронно, а где нет. Также существуют такие понятия, как CPH (callback pyramid of hell), asynchronous soup и так далее. Все они призваны обозначить код людей, которые очень любят писать все в одной функции. Для них было придумано великое множество flow control библиотек и даже диалектов js. Мои любимые — flow-js [4] и IcedCoffeeScript [5].

Однако, как оказалось, это не решает проблемы, а лишь позволяет программистам освоившим это дао, ехидно посмеиваясь, отправлять своим коллегам код с предложением проверить и принять пуллреквест.

И здесь мы возвращаемся к meteor. На стартовой странице meteor [6] есть 8 пунктов, которые описывают его основные особенности, нас интересуют два: live page updates (обновления страницы «на лету») и latency compensation (компенсация задержек). Вместе эти два свойства позволяет вам творить магию: связывать куски шаблонов с данными. При этом, как только данные изменились кусок шаблона заново рендерится и клиент получает актуальное состояние вашего приложения, тогда как вы не написали ни одной лишней строчки.

fragment = Meteor.render ->
    name = Session.get("name") or "Anonymous";
    "<div>Hello, #{name}</div>"

document.body.appendChild fragment 
Session.set("name", "Bob") # страница автоматически обновляется!

Пример взят прямо из документации. Если вкратце, то происходит следующее: есть «волшебный» метод Meteor.render, который возвращает documentFragment и умеет обновлять его в момент, когда изменяются данные, использованные в его теле. Одно условие: структура данных, с который мы хотим связать шаблон, должна реализовывать определенный интерфейс. Подробнее можно прочитать в описании Meteor.deps [7], а так — «it just works».

База данных on the wire

Дальше — больше, связывать данные с шаблоном это круто, но у нас все еще остается куча рутиного кода, который реализует синхронизацию данных на клиенте с данными на сервере. И тут, эти парни лихо рубанули с плеча и реализовали то, за что я их обожаю, а большая часть js-community нещадно гнобит. Database Everywhere. Они сделали прозрачным процесс добавления данных с клтиента на сервер. Вы меняете коллекцию на клиенте и она тут же через веб-сокеты синхронизируется с сервером. Дальше вступают в силу предыдущие два принципа и мы получаем, что у всех клиентов, которых затронули изменения, перед глазами актуальная страница. То есть по сути мы можем напрямую связывать БД и шаблон. Это просто:

Posts = new Meteor.Collection 'posts'
if Meteor.isClient
  $(@el).html Meteor.render ->
    someTemplateFunction Posts.find({}).fetch()

Обратите внимание, что строчка с объявлением коллекции должна исполняться как на клиенте, так и на сервере, а вот шаблонизатор должен запускаться на клиенте.

А как же безопасность? Буквально пару дней назад вышла версия 0.5, в которой был добавнлен механизм авторизации, который очень просто работает (на самом деле эти возможности уже довольно давно были доступны в ветке auth):

Posts.allow
  insert: -> false
  update: -> false
  remove: -> false
  fetch: -> true

Мы только, что запретили делать с коллекцией Posts любые действия, кроме выборок. Подробно можно почитать в документации [8] или на github [9].

На данный момент есть проблема с коллекциями большого размера, так как процесс их синхронизации занимает много времени и памяти. Сейчас эти проблемы решаются, например, вот тут [10].

В итоге, meteor позволяет нам писать код, который изначально ориентирован на данные и их изменения. С нас снимают необходимость думать о передаче инфрмации и о том, как нам поддерживать актуальность html после изменений на сервере.

Осталось добавить один небольшой штрих и сказать, что изначально весь код, который вы пишите, исполняется на сервере и на клиенте, а значит определения структур данных можно описать один раз и они будут одинаковыми везде. А, как известно [11]: «Bad programmers worry about the code. Good programmers worry about data structures and their relationships».

Код же, который относится только к клиентской части или должен исполняться только на сервере, нужно хранить в папка client и server соответственно. В общем, convention over configuration [12].

Deploy?

Механизм деплоя встроен в сам фрэймворк, но деплоится пока можно только на поддомены meteor.com, что конечно не круто. Для тех, кто уже хочет разворачивать meteor-приложения на своих серверах в документации есть подробная инструкция [13]. Ну, а я написал небольшой cake task [14], который автоматизирует этот процесс. Вам понадобится установленный forever [15] на сервере и установленные для текущего проекта npm-пакеты NodeSSH и scp. Для установки последних зайдите в «папка-проекта/.meteor/local/build/server/» и наберите: «npm install NodeSSH scp». Для запуска деплоя надо просто набрать «cake deploy».

И наконец

И в конце концов, я хочу заверить вас, что все среды и все фрэймворки меркнут перед meteor, когда речь заходит об удобстве разработки. Тому причиной две вещи, meteor практически никак не ограничивает вас в том, где и какие файлы вы хотите хранить, а второе — «Smart Packages». Я, как человек, который давно отвык программировать на чистом js и использовать чистый css, просто тащусь от факта, что любой созданный в директории проекта файл должен образом подключится к странице, а если я наберу простую команду в консоли: meteor add coffeescript, то любой созданный мной .coffee файл автоматически скомпилируется в js и будет добавлен к странице. То же самое можно сказать про такие вещи как less, stylus, sass и т.д.

Так же легко добавляются и различные плагины для jquery, языки фрэймворки и многое другое. По мере роста кол-ва «Smart Packages» meteor будет становиться все удобнее и удобнее, но даже сейчас там есть почти все необходимое для развертки полноценного one page app.

Что касается коммьюнити, то оно радует. Если вы зайдете на irc канал chat.freenode.net #meteor, вам обязательно помогут или хотябы попытаются помочь. На issue в github [16] реагируют быстро, а обсуждения довольно активны.

Несмотря на все дифирамбы, meteor все же пока не готов для серьезных продакшн решений. Также, очень грустно, что авторы так сильно привязали свое решение к mongo. Не то чтобы mongo плохая БД, но уже не модная. Предчувствую, что, однажды, авторам придется потратить приличное количество времени, выпиливая зависящий от mongo код, в попытке сделать meteor DB agnostic (не зависящим от конкретной базы данных).

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

P.S. Все примеры на CoffeeScript. А меня можно найти тут: @thought_sync [17] и http://github.com/Termina1 [18]

P.P.S. А еще EvilFaeton [19] сказал, что картинок мало, поэтому вот вам утренний бонус от команды ResumUP.

Thinking Reactively. Meteor JS

Ссылки:

  1. github: https://github.com/meteor/meteor [20]
  2. stackoverflow: http://stackoverflow.com/questions/tagged/meteor [21]
  3. Делают гении: http://meteor.com/about/people [22]

Автор: Terminal


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

Путь до страницы источника: https://www.pvsm.ru/javascript/17669

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

[1] странице документации: http://docs.meteor.com/

[2] backbone: http://backbonejs.org/

[3] мышления: http://www.braintools.ru

[4] flow-js: https://github.com/willconant/flow-js

[5] IcedCoffeeScript: http://maxtaco.github.com/coffee-script/

[6] стартовой странице meteor: http://meteor.com/

[7] Meteor.deps: http://docs.meteor.com/#meteor_deps

[8] документации: http://docs.meteor.com/#allow

[9] github: https://github.com/meteor/meteor/wiki/Getting-Started-with-Auth

[10] тут: https://github.com/meteor/meteor/issues/207

[11] как известно: http://lwn.net/Articles/193245/

[12] convention over configuration: http://en.wikipedia.org/wiki/Convention_over_configuration

[13] подробная инструкция: http://docs.meteor.com/#deploying

[14] cake task: https://gist.github.com/3928508

[15] forever: https://github.com/nodejitsu/forever

[16] issue в github: https://github.com/meteor/meteor/issues

[17] @thought_sync: http://twitter.com/thought_sync

[18] http://github.com/Termina1: http://github.com/Termina1

[19] EvilFaeton: http://habrahabr.ru/users/evilfaeton/

[20] https://github.com/meteor/meteor: https://github.com/meteor/meteor

[21] http://stackoverflow.com/questions/tagged/meteor: http://stackoverflow.com/questions/tagged/meteor?sort=newest&pagesize=15

[22] http://meteor.com/about/people: http://meteor.com/about/people