Thinking Reactively. Meteor JS

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



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


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

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

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

    Reactivity


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

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

    И здесь мы возвращаемся к meteor. На стартовой странице meteor есть 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, а так — «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 любые действия, кроме выборок. Подробно можно почитать в документации или на github.

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

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

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

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

    Deploy?


    Механизм деплоя встроен в сам фрэймворк, но деплоится пока можно только на поддомены meteor.com, что конечно не круто. Для тех, кто уже хочет разворачивать meteor-приложения на своих серверах в документации есть подробная инструкция. Ну, а я написал небольшой cake task, который автоматизирует этот процесс. Вам понадобится установленный forever на сервере и установленные для текущего проекта 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 реагируют быстро, а обсуждения довольно активны.

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

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

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

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



    Ссылки:


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

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 64

      +4
      Очень неоднозначный фреймворк…
        –1
        Почему же?
          +1
          да хотя бы потому что авторы клали на REST.
            –2
            А, ну ладно.
          –1
          Еще более неоднозначная преамбула к посту.
          +2
          На хабре было уже как минимум 3 introduction статьи про метеор
            +1
            А можно статью на хабре, где не просто перевод главной страницы или анонс новой версии? Я пользовался поиском, но ничего не нашел?
            +8
            А сложно ли с него слезть? Вот понаписал я что-то по-быстрому в качестве прототипа. А потом решил сменить среду, много ли мне придется понаписать, чтобы оторваться от зависимостей Meteor JS?
              +7
              Примерно так же просто как слезть с RoR
                –1
                А, если серьезно, то все зависит от кол-ва smart packages, которые вы используете
                +28
                >>>Если вы еще не слышали про meteor, значит вы вообще не следите за миром JavaScript, не интересуетесь вебом и непонятно каким образом сюда попали.
                пффф
                  +2
                  . Вместе эти два свойства позволяет вам творить магию: связывать куски шаблонов с данными. При этом, как только данные изменились кусок шаблона заново рендерится и клиент получает актуальное состояние вашего приложения, тогда как вы не написали ни одной лишней строчки.

                  Knockout.js с понтами и дифирамбами.
                    0
                    Вот кстати было бы интересно посмотреть, как это реализовано у них внутри, и сравнить с нокаутом.

                    Как известно, браузер начинает давать немалые тормоза, если модель в knockout большая, а шаблон, который нужно отобразить содержит внушительное количество связей с observables. Может быть, товарищи в meteor смогли справиться с этой задачей?
                      0
                      А как бы они это могли сделать? Рендер куска страницы дело вообще небыстрое, так что в большом шаблоне хочешь-не хочешь, а придётся погонять процессор.

                      Но даже если и можно придумать какой-то обходной путь, сомневаюсь, что на данном этапе они этим вопросом сильно занимались.
                        0
                        Ну как… как и всё, что делается быстрее. Проводятся сравнительные анализы, и — вот результат.
                        Надуманный пример: что проще: удалить ноду и вставить новую или обращаться к ее innerHTML? А если 10 000 раз? Думаю, таких примеров можно придумать много. Остаётся их комбинировать и jsperf.com.

                        Ну и не забывайте, что мы с вами про JavaScript говорим — под капотом всё не так просто :)
                      0
                      мне кажется их даже сравнивать не правильно, и в начале я попытался это объяснить.
                        0
                        А что неправильно? Для Нокаута уже сто лет в обед как есть плагин для синхронизации всего и вся — а в этом как раз и есть основная «фишечка» метеора. Причем на Нокауте это не сделано в ущерб всему остальному. И Нокаут — не единственный в этом роде. Синхронизация есть и для Backbone, и для Angular, и это только те, про кого я могу навскидку сказать.

                        Кроме того есть вообще такая штука: parse.com — это полный бекенд для вашего приложения. Там есть storage, user management, server-side JS, push notifications. Они в основном позиционироуют этот продукт как серверную платформу для мобильных приложений, но у них также есть и полниценный JS SDK для приложений в браузере. Есть фришная квота, вполне преемлимая, слезть с них при случае будет не сложно. Причем, в отличие от этого Метеора, который появился невесть откуда и пропал на полгода, эти ребята — устойчивый и приносящий прибыль бизнес.
                          +2
                          Окей, вы безусловно правы и оень логичны. У меня закончились аргументы.
                            0
                            Кстати, нашел интересную ссылку в инернете meteor.com/blog/2012/07/25/meteors-new-112-million-development-budget
                              +1
                              Аргумент ожидался.

                              И что? В результате ребята, вместо того, чтобы обкатывать проект на реальном приложении (а-ля Basecamp в случае с Ruby-on-Rails), сидят и пилят его непонятно для кого. У них есть фреймворк, который создается без цели и без «боевого крещения» — ребята просто просиживают денежки в надежде на aquihiring.

                              Те же авторы Angular рассказывали, как их фреймворк вырос из реального проекта внутри Google, а автор Knockout вообще перерабаотывал его три раза в течение нескольких лет.
                                –1
                                И это доказывает, что Meteor — ерунда?
                        +14
                        Не то чтобы mongo плохая БД, но уже не модная.
                        Адский довод. Надо будет в копилку аргументов добавить (сарказм).
                          +1
                          Я надеюсь, мой сарказм вы тоже уловили.
                            0
                            А какая сейчас модная?
                            0
                            Знаете, почему, например, под Unix системы какую-то «модель» можно реализовать очень многими способами? Потому что каждая часть самостоятельная, можно быстро заменить одну другой (в случае неотказоустачивойсти, например).

                            Насколько просто можно в данном фреймворке одну часть заменить другой?
                              –1
                              У авторов изначальо стояла задача максимально облегчить ядро фрэймворка, поэтому если вы заглянете в их репозиторий, то увидите, что основной код находится в в packages, которые можно включать и отключать.
                            0
                            В одном с прошлых топиков жаловались на то, что он делает POST запрос на бекенд каждую секунду, это исправилось?
                              –1
                              Вообще, он с сервером общается через веб-сокеты, если они есть. С фолбэком на AJAX.
                                –3
                                А почему на AJAX, а не, скажем, comet?
                                  –1
                                  Ну, сейчас начнётся холивар :) Ребята выбрали сокет, вероятно, оставили вам возможность написать другой транспорт.
                                    –1
                                    С сокетами как раз все понятно, вопрос был почему фолбэк на AJAX а не на comet
                                      +2
                                      Ну что вы, в самом деле. Автор топика — не разработчик. На остальное ответ такой:
                                      Ребята выбрали AJAX, оставив вам возможность реализовать через Comet.
                                    +1
                                    А что вы имеете ввиду под comet?
                                      0
                                      http://en.wikipedia.org/wiki/Comet_(programming)
                                      Бомбить запросы каждую секунду ну как-то уж совсем некрасиво.
                                        0
                                        реализация с iframe — это не хорошо, потому что мы занимаем целый коннекшн, для node.js — это очень плохо. То же самое с long-polling. Не забывайте, что мы работаем на одном ядре. А так, WebSockets — это самый правильный Comet, и так.
                                          –2
                                          А с другой стороны, пользователи мобильного интернета, зашедшие браузером который не поддерживает WebSocket'ы просто вас проклянут.
                                            –1
                                            Пускай часть пользователей будут недовольны, зато сервер будет жить.
                                              0
                                              Отличный подход: переложить проблемы на пользователей, ли ж бы нам было хорошо :)
                                              Ничего личного, но я считаю такую концепцию ущербной.
                                              Остается молится о скором вымирании старых браузеров.
                                                0
                                                Я говорю о том, что если выбирать между тем, чтобы сервис вообще не работал и тем, чтобы у части пользователей были проблемы (кстати, когда тестил в ie8, никаких неудобств серьезны не заметил), лучше выбрать второй вариант.
                                                  +1
                                                  Либо другой фреймворк ;)
                                            0
                                            А можно по подробней про nodejs, целый 'коннекшн', WebSocket, одно ядро и почему же всё таки MongoDB 'не модно'.
                                              0
                                              Meteor(а в целом и nodejs) работает в одном потоке, слышали? Не модно — значит не модно, такое мое субъективное мнение. WebSockets — почитайте тут ru.wikipedia.org/wiki/WebSocket
                                                0
                                                Спасибо за содержательный ответ.

                                                Nodejs.
                                                Ваш код в nodejs работает в одном потоке. Сам nodejs является отдельным процессом.
                                                Про одно ядро я бы не стал вообще упоминать тут.

                                                Вы улавливаете разницу между потоком, процессом и ядром?
                                                Если да, то пожалуйста расскажите не поленитесь, я думаю
                                                многим будет интересно, мне точно, особенно в контексте
                                                javascript-а.

                                                MongoDB.
                                                Хорошо ваше право считать что MongoDB не модно.
                                                Но хотелось бы услышать альтернативы.
                                                И почему у вас сформировалось такое мнение про MongoDB,
                                                возможно после того как вы опишите те проблемы с которыми
                                                вы столкнулись в MongoDB мне тоже покажется
                                                что это не модно.

                                                WebSocket.
                                                Спасибо за ссылку про WebSocket, прочитал.
                                                Но появились вопросы:
                                                — Что для вас означает 'коннекшн'?
                                                — Как nodejs-у мешает 'коннекшн'?
                                                — Как вас спасает WebSocket от 'коннекшн'-а?

                                                Спасибо.
                                                  –2
                                                  Node.js использует событийный ввод/вывод (epoll, kqueue, select) и работает на EventLoop и является одним процессом, который может держать большое число соединений за счет снижения накладных расходов.

                                                  За всю сессию работы WebSocket поднимает только одно соединение на ввод и вывод в отличии от LongPolling где каждый запрос — новое соединение (новые соединения — это порты, а они кончаются порою быстрее, чем уходит память).
                                                    0
                                                    Насчет того, что LongPolling на каждый запрос создаёт новое TCP соединение — далеко не факт. man keep-alive, как говорится.
                                                    Насчет того, что новые соединения это новые порты — это вы о чём вообще???
                                  +2
                                  Однако, как оказалось, это не решает проблемы, а лишь позволяет программистам, освоившим это дао, ехидно посмеиваясь, отправлять своим коллегам код с предложением проверить и принять пуллреквест.
                                  И как же после этого абзаца следует понимать примеры на кофескрипте вместо джаваскрипта? Чувствую, что Terminal похихикал злоехидно.
                                  +1
                                  Если вы еще не слышали про meteor, значит вы вообще не следите за миром JavaScript, не интересуетесь вебом и непонятно каким образом сюда попали.

                                  Что за выводы такие? Манна небесная, что ле этот ваш фреймворк? И как раньше без него приложения делали, даже не знаю. Наверно сейчас они все развалятся.
                                    +2
                                    На мой взгляд knockout, meteor и другие аналогичные фреймворки очень уж сильно пытаются упростить жизнь, дико ее усложняя своими внутренними процессами. Пробовал все, но лучше backbone не нашел – все под контролем программиста, гибко и красиво; жизнь упрощает, но не слишком.
                                      +1
                                      Мне очень грустно, что я не смог донести до аудитории, что meteor — это не про MVC, это про реактивность, а backbone в meteor интегрируется одной командой.
                                    0
                                    Фреймворков этих наплодилась тьма. Выбрать нужный поможет взгляд на решение одной и той же задачи на каждом из фреймворков. Например, тут: addyosmani.github.com/todomvc/ реализация TODO приложения
                                      +3
                                      Делают гении: meteor.com/about/people
                                      Не, не слышал.
                                        –1
                                        Вы правы, это объективный показатель.
                                        0
                                        Если честно я так и не понял, на кой черт эта штука нужна, и что она делает. Это потому что метеор это что-то очень крутое, для очень крутых? Или все причина в другом?
                                          –2
                                          Возможны оба варианта.
                                            +1
                                            Вот я тоже прочитал, и понял что это типа что такое, после изучения которого можно будет не боясь ходить в темном переулке и рассказывать какой я крутой)

                                            я хотелось бы побольше живых примеров.
                                              0
                                              в следующей статье будет живой пример
                                                –1
                                                Так надо сразу его приводить.
                                            –1
                                            Сплошь из гениев — это, видимо, типа того, но хз, больше похоже на «маркетинг» с целью выбить миллиард на инвестиции из доверчивых вкладчиков (что уже, по-моему, и было сделано).

                                            Сам ни разу не пользовался этим фреймворком, и пока не собираюсь, т.к. в нём нет ничего, что было бы мне нужно (как в твиттере или фейсбуке).

                                            Единственная вещь, которая меня в нём заинтересовала — это вот это: «Вы меняете коллекцию на клиенте и она тут же через веб-сокеты синхронизируется с сервером.»

                                            Как так?
                                            Как они это сделали?

                                            Я продумывал в своё время такую схему на MongoDB, и не пришёл к решению.
                                            Просто решил, что это пока невозможно.
                                            Если у них идеально рабочее решение, и не костыль с багами, то это будет круто.
                                            Исходники их читать неохота, поэтому если кто-то подробно объяснит, в чём состоит алгоритм их чудо-синхронизации — буду благодарен.

                                            Only users with full accounts can post comments. Log in, please.