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

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

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

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

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

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

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

Я не в теме, но предполагаю, что организовать защиту закрытого кода от пиратства будет проблематично.
Да, Saas — это определенно будущее для всех приложений.
Но банкиры скажут «слишком большие риски». Попробуй им объяснить.
Технологии уже созрели. Теперь надо подождать пока в головах поменяется.
Жестко ли привязан шаблонизатор к Derby.js? Есть ли возможность использовать что-то стороннее (например, Swig, а еще лучше прикрутить что-то вроде consolidate)?
Попробовал.

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

> npm install -g derby

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

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

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

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

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

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

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

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

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

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

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

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

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

npm install Тут доки
Если просто версии обновить, то:
npm update Тут доки
У 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'.

Выручай!
Это не то чтобы для извращенцев. Если так, то почти все 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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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);


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

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