Веб-разработчик
0,0
рейтинг
30 сентября 2013 в 18:25

Разработка → Hello World на Derby.js tutorial



Если вам не безразличны новые тендеции веб-разработки, то приглашаю поучаствовать в дискуссиях в комментариях к посту Angular vs Meteor vs Derby. Там много интересных мыслей.

Ну а тем временем неделя Derby.js на Хабре продолжается. Популяция Derby-программистов удваивается. И сегодня мы будем учиться бегать на страусах настраивать окружение, создадим приложение, запустим и рассмотрим его структуру.
Если для вас это уже пройденный этап, возможно вам будет интересно посмотреть Tutorial, который по сути Faq. Остальным добро пожаловать под кат.


Окружение


Будем считать, что у вас Linux семейства Debian (Ubuntu, Debian и т.п.). Настройка окружения для других ОС: другие Linux, Windows, Mac OS имеет свои особенности, но принципиально не отличается.
Для того, чтобы запустить Derby приложение, нам нужно: node.js, mongodb, redis (минимум 2.6).

Для node.js и redis, мы будет использовать репозитарий chris-lea, у mongo есть официальный.

# Добавляем репозитарии
# node.js
sudo add-apt-repository -y ppa:chris-lea/node.js
# mongodb
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
sudo echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/10gen.list
# redis
sudo add-apt-repository -y ppa:chris-lea/redis-server

# Обновляем apt-get
sudo apt-get -y update

# Устанавливаем
sudo apt-get -y install nodejs
sudo apt-get -y install mongodb-10gen
sudo apt-get -y install redis-server


Приложение


Мы конечно можем сейчас запилить приложение с нуля. Что нам стоит дом построить?
Но в Derby есть утилита, которая генерирует для нас макет приложения и экономит время. Почему бы нам не воспользоваться этим?
Для этого нам нужно установить npm пакет derby глобально:

sudo npm install -g derby


Создаем приложение, с названием hello-derby (это будет также название папки):

derby new hello-derby


Утилита создаст нам приложение и установит все зависимости. Это займет какое-то время и в конце вы увидете:

  Project created!

  Try it out:
    $ cd hello-derby
    $ npm start

  More info at: http://derbyjs.com/


Мы будем рассматривать js приложение, но если хотите Coffeescript, используйте --coffee, -c:

derby new --coffee my-cool-coffee-derby-app


Также можно создать пустое приложение (только макет):

derby bare my-bare-app


Или создать приложение, но не устанавливать зависимости при помощи --noinstall, -n:

derby new -n empty-node_modules-app


Запускаем


Чтобы запустить, как вы уже догадались, нужно:

cd hello-derby
npm start


Видим:

1234 listening. Go to: http://localhost:3000/


Теперь в браузере идем сюда: http://localhost:3000/
Ура, работает!

Структура


Давайте быстренько пробежим по структуре проекта.

/lib — тут почти весь js. Если вы на coffee, то будет папка /src.
/lib/app — это то, клиентское приложение с названием app. Таких приложений может быть несколько. В общем это то, что может выполняться на сервере и также загрузится на клиент.
/lib/app/index.js — тут создается само приложение, добавляются компоненты 'derby-ui-boot'(это bootstap для derby) и 'ui'(это пользовательские компоненты). Затем создаются routes, которые будут исполняться и на сервере и на клиенте. В конце создаются контроллеры — это функции, которые исполняются только на клиенте и связанны с манипуляциями dom.
/lib/server — это серверное приложение. Может быть только одно. Тут код, который выполняется только на сервере и с клиента напрямую не доступен.
/lib/server/error.js — здесь мы генерируем пользовательские статичные странички ошибок (без клиентского приложения).
/lib/server/index.js — здесь создается express.js приложение, настраиваются базы данных, создается store, добавляем в express app модули connect, некоторые их которых являются частями Derby приложения. В конце создается server-side route, который выдает ошибку если до этого не сработал ни один route.
/node_modules — тут npm пакеты.
/styles — тут стили. По умолчанию Stylys. Могут быть разными для разных клиентских приложение (по именам папок). В ui — стили компонентов.
/ui — тут компоненты. Каждый компонент состоит из js и html файлов и находится в папке со своим имененм.
/ui/connectionAlert — это пример компонента. Если клиент ушел в оффлайн, этот компоненты выводит соответсвующую надпись и кнопку «Reconnect». Если переподключиться не удалось, он предлагает перезапустить приложение «Reload».
/ui/index.js — тут общие настройки компонент.
/views — html темлейты.
/views/app — тут те темплейты, которые загрузятся в клиентское приложение app.
/views/app/home.html — это стартовая страница.
/views/app/index.html — это layout для home.html и list.html.
/views/app/list.html — лист.
/views/error — тут лежат темплейты для ошибок, которые мы загружаем из /lib/server/error.js
.npmignore — это вам нужно будет если вы свое приложение будете публиковать в npm как пакет.
Procfile — это для Heroku
README.md — прочитай меня
package.json — это настройки для npm. Тут указаны все ваши зависимости. А так же что делать, если вы набрали npm start.
server.js — самый главный файл. Точка входа вашего приложения. Тут Derby запускает express приложение.

Материалы по Derby.js
Махаев Владимир @vmakhaev
карма
13,0
рейтинг 0,0
Веб-разработчик
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (38)

  • 0
    Вы планируете продолжение?
    Думаю интересно будет подробнее разобрать структуру MVC.
    Сама документация Derby.js достаточно скупая.
    Кстати достаточно спорное решение свалить все контроллеры и роутеры в один файл: /lib/app/index.js
    • +1
      Продолжение планирую. В следующей статье думаю написать какое-нибудь не очень сложное приложение.
      MVC рассмотрим. Что еще не понятного?
      Документация скудная, согласен, исправляем.

      Для такого размера приложения — нормально свалить всё в кучу. Но в общем вы правы.
  • 0
    Ещё интересно, и даже очень, — кеширование.
    Как внедряется, как реализуется в Transitional routes. Где его стоит использовать (в контексте Derby.js), где нет.
    Интересует тема Access Controls — в документации в стадии coming soon
    • 0
      Что вы имеете ввиду под кешированием в Transitional routes?
      Transitional routes — это когда вы хотите изменить url, но поменять не весь UI, а только часть.
      При чем тут кэширование?

      По Access Control
      • 0
        Ok, уточняю — имел ввиду именно кеширование фрагментов/частей.
        • 0
          Я всё равно не понимаю вопроса.
          Transitianl routes в большинстве случаев (если не попал на певый запрос к серверу) отрабатывается на клиенте. Что вы там хотите кэшировать и для чего?
          Темплэйты в Derby и так хранятся в «готовом для употребления виде» ввиде js функций. Которые проглатывают модель и моментально выплевывают html.

          Опишите, пожалуйста, подробней что вы имеете ввиду.
          • 0
            Вопрос был в том — в каких случаях целесообразно применять кеширование, а в каких нет.
            С ransitianl routes ситуацию в целом вы прояснили. Однако общий вопрос с «кешированием», как пожелание, остается.
            • 0
              По проводам передаются даже не данные, а операции OT, которые ловятся через pub-sub редиса и раскидываются по клиентам. В redis лежит кэш этих операций.
  • 0
    Не множко вопрос не по теме, но вот мне кажется, что Derby.js очень подходит для разработки корпоративных web-приложений — сразу из коробки есть почти все что нужно для реализации совместной работы, а чего нет, можно найти в npm. Но вопрос в следующем — можно ли каким-нибудь образом реализовать защиту своего приложения с возможностью выдачи лицензий с привязкой к оборудованию?
    • 0
      Да. Derby идеально подходит для ваших целей.

      Привязываться к оборудованию клиентов будете? По IP? Если так, то не проблема. IP передаётся в каждом http-запросе. Фильтруйте на здоровье.
      • 0
        Не по IP, а хотябы по хешу от мак адреса и серийного номера жесткого диска. Ну и сам код необходимо как-то зашифровать, чтобы нельзя было найти функцию проверки лицензии и удалить её.
        • 0
          Вот здесь справедливо говорят, что возможность узнавать mac-address средствами js в браузере — потенциальная уязвимость.
          Js на клиенте можно обфусцировать, но это всё равно не машинный код, как вы понимаете.

          В той же ссылке рекомендуют использовать Java-апплет. Вы можете делать приложеие на Derby и функцию выдачи лицензии на Java-апплет. Наверное это и будет решением.

          Что у вас за приложение раз нужна такая сильная защита?
          • 0
            Серверный js узнает и mac и любую другую информацию о сервере и лицензия выпускается на сервер — поэтому код, который запускается на этом сервере должен работать только на нем. Сейчас все это решается средствами Zend Guard.
            А приложения — небольшие web-приложения для проведения аналитики информационной безопасности в банках.
            • 0
              Ах. На сервере. Я не так понял. Дак тут вообще проблем нету никаких.
              Так и понял что что-то с банками у вас.
    • 0
      Это мир чистого open source. Чтобы зарабатывать деньги, организуйте SaaS.

      Я не в теме, но предполагаю, что организовать защиту закрытого кода от пиратства будет проблематично.
      • 0
        Да, Saas — это определенно будущее для всех приложений.
        Но банкиры скажут «слишком большие риски». Попробуй им объяснить.
        Технологии уже созрели. Теперь надо подождать пока в головах поменяется.
  • 0
    Жестко ли привязан шаблонизатор к Derby.js? Есть ли возможность использовать что-то стороннее (например, Swig, а еще лучше прикрутить что-то вроде consolidate)?
    • 0
      Наверно можно прикрутить. Вот, например, Jade прикрутили.
  • 0
    Повалило: habrahabr.ru/post/195812/
    • 0
      Ура, ура, ура! Значит всё не зря.
  • 0
    Попробовал.

    Поскольку Redis под виндой без плясок с бубном не работает, запустил на Linux в виртуалке.

    > npm install -g derby

    Это без sudo не сработало.

    По итогам ознакомления со структурой проекта Derby возник вопрос: что это за монстр node_modules/?! Эта папка содержит 13 тысяч файлов и занимает 100 мебибайт! Новый голый проект в IDE (через сетевую ФС) загружался несколько минут!

    Там что, хранится код всех используемых в проекте библиотек? А если я создам десять новых проектов, они будут весить гигабайт? О_О Для человека, привыкшего к пакетному менеджеру Ruby (RubyGems и Bundler) это какой-то адский ад! Зачем это нужно, почему не хранить один экземпляр этого добра централизованно в системе?

    Я надеюсь, в систему контроля версий их чекинить не принято? Но если я использую самописные модули, то придется в .gitignore прописывать исключения из исключений?
    • 0
      Добавил sudo. Спасибо за замечание.

      Что за проблемы с Redis под Windows? Здесь уже чего-то обсуждали про это.

      node_modules — это место храниение npm пакетов. То есть всех зависимостей твоего приложения.
      Ты можешь установить все свои зависимости глобально, по примеру npm install -g derby, тогда они будут лежать в общей папке (в разных ос в разных местах) и использоваться всеми приложениями. Но тут рекомендуют так делать только для пакетов, которые используются в shell (как derby утилита, например). Остальные пакеты обычно устанавливаются локально (в node_modules твоего приложения).

      Обычно node_modules добавляют в .gitignore, Но если ты деплоишь из git, то возможно лучше чекинить.
      Самописные модули ты выкладываешь на github и в package.json прописываешь git-путь.
      • 0
        Это ненормально. Это же стандартные пакеты. Зачем плодить десятки совершенно идентичных копий всех пакетов? По сути, для каждого проекта создается свой локальный репозитарий. Если я насоздаю десятки учебных приложений, счет пойдет на гигабайты дублирующегося мусора. :(

        А уж в репозитории хранить всё это — это вообще за гранью добра и зла. Сколько времени будет идти клонирование репозитория с GitHub, мне даже страшно представить.

        Как сделать derby new так, чтобы использовался единый локальный репозиторий в системе? Какой командой установить зависимости при деплое этого проекта на сервер?
        • 0
          У npm такая идеология. Это позволяет использовать разные версии пакетов для разных приложений и в пределах одного приложения.
          Если не будешь увлекаться созданием приложений, то в реальности это не так много места.

          Я же сказал, что в основном не хранят в репозитарии. Но бывают исключения. Я, например, не храню.

          Как сделать derby new так, чтобы использовался единый локальный репозиторий в системе?

          Ты имеешь ввиду единый глобальный репозитарий? Попробуй derby new -n. Это создаст проект без установки зависимостей.

          Какой командой установить зависимости при деплое этого проекта на сервер?

          npm install Тут доки
          Если просто версии обновить, то:
          npm update Тут доки
          • 0
            У npm такая идеология. Это позволяет использовать разные версии пакетов для разных приложений и в пределах одного приложения.

            Какая-то на редкость унылая идеология.

            Сравниваю с Ruby, с которым имею честь быть знаком. RubyGems позволяет устанавливать любые версии пакетов в центральный локальный репозиторий. Существует RVM, который в числе прочего позволяет устанавливать окружение Ruby на уровне пользователя, тогда для установки пакетов в центральный локальный репозиторий не требуются права администратора. Bundler позволяет составлять произвольный набор пакетов любых версий индивидуально для каждого проекта. Если же нужны несколько версий одного пакета (зафига? вам хоть раз это требовалось? как при этом разрешается конфликт имен?), можно именно этот пакет положить в папку проекта и подключать по относительному пути.

            Волочить проекты размером в сотни мегабайт с десятками тысяч файлов (фак мой мозг!) при том, что собственного кода у проекта может быть один килобайт в трех файлах — это жесть! И всё ради чего? Чтобы какой-то извращенец мог без лишних хлопот запустить две версии одного пакета?

            Попробуй derby new -n.

            Сделал так:

            derby new -n hello_derby2
            cd hello_derby2
            sudo npm install -g
            


            Теперь объем проекта 12 КиБ, количество файлов: 24. Совсем другое дело.

            Но запустить не получается. :( Если делаю npm start, выдает ошибку «UNMET DEPENDENCY». Если sudo npm start, выдает Cannot find module 'derby'.

            Выручай!
            • +1
              Это не то чтобы для извращенцев. Если так, то почти все node.js программисты — извращенцы в какой-то степени :-)
              В каждом более менее большом проекте очень сложное дерево зависимостей. Это возможно связано с node.js и javascript, Мне трудно сравнивать с Ruby, я на нем почти не программировал, а разбираться сейчас уже не вижу смысла. В общем пакет A может иметь зависимостью пакеты B и С, а пакет B тоже зависим от пакета C. Это могут быть разные версии C. Если одна и та же версия, то он установится один раз в пакет A, а если разные то 2 раза (в A и B), Я думаю теоритически можно найти и другие способы разрешения таких ситуаци — какое-нибудь глобальное хранилище пакетов с возможностью сосуществования разных версий или еще как-то. Разные решения наверно имеют разные плюсы и минусы. Но в npm решили сделать так. Спроси у него почему. Что я тебе точно могу сказать это то, что npm очень молод и создавался с оглядкой и по опыту других пакетных менеджеров.

              Эх. Тебе же рекомендовали все пакеты устанавливать локально для каждого приложения. :-) Как в воду глядели.
              Ты пошел своим путем. :-) Зато разобрался с npm и я тоже вместе с тобой :-)
              sudo npm install -g — эта штука не устанавливает все зависимости глобально. Их нужно устанавливать по очереди.
              sudo npm install -g derby
              sudo npm install -g express
              sudo npm install -g redis
              sudo npm install -g livedb-mongo
              sudo npm install -g racer-browserchannel
              sudo npm install -g connect-mongo
              npm start
              


              Но я всё равно тебе не рекомендую так делать. Удали уже пару фильмов или музыку там какую-нибудь и найди место.
              • 0
                Тут пишут, что нужная команда — npm link. Создает символическую ссылку из project/node_modules/имя_пакета на папку пакета в центральном локальном репозитории.

                Ладно, не буду идти против системы. Поскольку npm поставит раком мой Dropbox, придется привыкать держать исходники в другом месте.

                Извините за истерику. :)
              • +1
                Разные решения наверно имеют разные плюсы и минусы.

                Вот, что я выяснил.

                У JS область видимости ограничена функцией, что позволяет прямо во время выполнения программы в разных ее частях использовать разные версии одного и того же пакета. При этом никаких конфликтов не будет. Ни Ruby, ни другие известные мне языки так не умеют.

                А недостаток этого подхода — в чудовищной дупликации пакетов. Как при хранении, так и при исполнении. К примеру, в новом пустом Derby-проекте один только пакет mongodb имеет 9 (девять!) дубликатов. Пруф: http://d.pr/i/kSV3+. И девять раз оно будет загружено в память. Я пообщался на irc://irc.freenode.net/node.js/, это действительно так!

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

                Еще они говорят, забей на Derby, это непомерно сложно не только для новичка. Начни, мол, с голого Node-проекта. :)
                • 0
                  Спасибо, что разобрался. Это будет полезно многим.

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

                  Я думаю если ты только начинаешь разбираться, то посмотреть на голый node.js проект полезно. И посмотреть их доки.
                  Так же нужно понимать концепцию middleware connect.js.
                  Посмотреть на голый express.js проект.

                  На голом node.js можно писать, но он довольно низкоуровневый и тебе прийдется изобретать кучу вещей за ново (велосипедить). Для большинства проектов этого делать не надо, так как уже всё придумано до нас. Но в некоторых случаях, если это так нужно, то node.js позволяет опустить на уровень ниже.
                  Обычно node.js оборачивают в connect.js, его в свою очередь в express.js. Derby.js — это обвертка над express.js.
                  Каждый новый уровень добавляет возможностей, хотя немножко сложнее в понимании, чем предыдущий.
            • 0
              не стоит так переживать.
              во1х Дерби — это не фреймворк для приложений на три страницы, как минимум его стоит брать туда где паб-саб не будет выглядеть наворотом/оверхедом. точно так же как и рубисты не берут Рельсы там где можно юзать Синатру (велкам Экспресс — чистая Синатра под ноду) или Падрино. а тут еще и две базы сверху навернуты.
              во2х, я видел полно руби-приложений где народ делает папочку vendor и хранит там все барахло перечисленное в Gemfile.lock. и както не страдает что если таких приложений будет 10 (ага, может лет через 5) то они прям забьют винт.
              в3х, npm прекрасно тянет зависимости для проекта из package.json, точь-в-точь как Bundler из Gemfile.
              • 0
                Переживания касались многократного дублирования копий пакетов — сначала внутри проекта, а потом между проектами. Вы эту проблему в своих трех аргументах не затронули.
              • 0
                Derby.js довольно гибкий. Уже писал об этом тут и прекрасно подходит для приложений на три страницы. Если вам не нужна бд, например, можно и без нее.

                Ваши опасения напрасны. На практике это не занимает много места.
  • 0
    Куда физически сохраняются данные демо-приложения? Я так понимаю, Redis и MongoDB запущены в качестве сервисов независимо от npm start?
    • 0
      Да, Mongo и Redis висят в виде сервисов. И наше приложение подключается к ним при запуске. В /lib/server/index.js есть настройки для бд.
      • 0
        Выходит, Mongo не использует по умолчанию ни пароль, ни даже ограничение на доступ по сети?

        Какими именно строчками кода задаются настройки подключения? Например, имя базы данных?

        Есть еще одна непонятная мне вещь. Я поработал с тестовым приложением, добавил несколько записей, но, запустив его повторно, не увидел внесенных записей. Тогда я внес другой комплект записей, и они уже стали сохраняться. То есть я мог перезапустить ноду, и записи оставались доступны. Когда же я заглянул в Mongo при помощи GUI-приложения для ковыряния в его недрах, то увидел в нем и старые, и новые записи. Почему же старые вдруг перестали быть доступны?

        Много, очень много непонятнок… Чтобы во всем разобраться, надо начинать с изучения голой Node. :(
        • 0
          Да. Многие монго без пароля в продакшен выкладывают :-)

          var mongoUrl = process.env.MONGO_URL || 'mongodb://localhost:27017/project';
          var store = derby.createStore({
            db: liveDbMongo(mongoUrl + '?auto_reconnect', {safe: true})
          , redis: require('redis').createClient()
          });
          

          Имя бд — project. Редис по умолчанию выбирает бд 1. Но можно выбрать, например, 2 вот так:
          var redisClient = require('redis').createClient();
          redisClient.select(2);
          


          Это интересный вопрос. Ты опять всё сломал? :-) Надо посмотреть что у тебя в редисе и в таблице операций.

          Путь к звездам долог и тернист :-)
      • 0
        Также прошу разъяснить, чем с практической точки зрения отличаются Redis и Mongo и зачем Derby нужны оба.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.