9. Глобальные модули

Следующая возможность которую мы с вами рассмотрим это глобальные модули. Любой модуль можно поставить глобально если поставить флаг «-g».

На «MAC» сразу может не получится, потому что глобально означает в системную директорию. Если операционная система поддерживает ограничение доступа, то как правило от обычного юзера, в системную директорию я писать не имею права. Для этого на «MAC» надо сделать запуск через команду «sudo» выглядеть это будет вот так

У меня же «Windows», а в «Windows» директория глобальных модулей находится внутри каталога юзера — C:\Users\имя_пользователя\AppData\Roaming\npm по этому ни каких особых разрешений для установки модулей глобально не нужно.

Screenshot_09_01

как видите в первой строке я ввел команду «npm -g i express». Помните мы с вами говорили о том, что «i» и «install» это одно и то же. Во второй строке показан путь куда «NPM» поставил наш модуль, давайте посмотрим

Screenshot_09_02

Так и есть, «NPM» создал папку «node_modules» и поставил туда «express» причем последней версии, так как мы ее не указывали в команде.

Чем глобальная установка отличается от обычной? В первую очередь это местом, глобальные модули ставятся в стандартную системную директорию. Второе, это то что те бинарники которые есть в свойстве «bin» в «package.json» будут поставлены по системному пути. Это означает, что бинарник «express»  я теперь могу вызвать просто вот так

Screenshot_09_03

Правда, для этого мне пришлось поставить третий «express», четвертый совсем другой. Это как раз то о чем мы говорили, что если новая версия ломает код использующий старую, то мы должны обновить мажорную версию. Подробней про миграцию с третей на четвертую версии «express» можно почитать здесь.

Любые дальнейшие операции с глобальными модулями осуществляют так же как с обычными, но с флагом «-g». Например верну себе обратно четвертый «express», обновлюсь

Screenshot_09_04

можно было просто ввести

обновились бы все глобальные модули которые есть у меня.

Зачем вообще нужны глобальные модули, перед тем как об этом говорить, развеем частые заблуждения связанные со словом «глобальный». Глобальный обычно означает, доступный на уровне системы, доступный всем. Глобальная переменная, это та к которой можно обратиться от куда угодно. Но в данном случае слово глобальный используется по историческим причинам. Когда то так и было, но сейчас, если модуль поставлен глобально то это не означает, что он автоматически становится доступен всем. То есть не смотря на то, что я поставил «express» глобально, если я где нибудь сделаю

то он модуля не найдет. Глобальный, в данном случае, означает, скорее, системный. И основное применение глобальной установки модуля, это сделать доступным бинарник по системному пути. Например, есть ряд утилит, написанных на «node.js», скажем есть «uglify-js», которая умеет сжимать javascript файлы. Эту утилиту я могу поставить глобально

Screenshot_09_05

Теперь, если мне надо сжать js файл я могу в консоле набрать

подробнее про «uglify-js» можно почитать вот здесь.

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

если хотите, посмотрите «help», но это не рекомендуется.

 

8. Структура пакета NPM

Для того, чтобы посмотреть на реальный «package.json» поставим модуль «express».

Screenshot_08_01

Этим модулем мы ещё будем пользоваться в будущем, а сейчас просто ставим этот внешний модуль и взглянем на его «package.json», как он выглядит

Здесь я позволил себе кратко прокомментировать некоторые строчки этого файла, на самом деле, конечно же, такой «package.json» работать не будет, потому что комментариев  в json не может быть, это делает json не валидным. Мы кратко пройдемся по некоторым особенностям «package.json», пока что в общих чертах, в дальнейшем, когда мы будем делать конкретные вещи, то мы используем это для решения конкретных задач.

Итак поля(в скобочках будет номер строки):
(2) «name»уже знаем
(3) «description» — описание, информационное поле, по нему осуществляется поиск при «npm search».
(4) «version» — версия имеет вид «MAJOR.MINOR.PATCH» и подчиняется спецификации semver. Что это значит? Это означает, что когда я делаю пакет, пока я его еще не опубликовал, или опубликовал, но не в законченном виде,  я делаю первый номер ноль

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

теперь каждый номер версии имеет конкретный смысл. Здесь последнее значение это патч — PATCH, если я вношу какие то незначительные изменения, скажем bug-fixing

Дальше, средний компонент это минорная версия. Минорная — MINOR версия обновляется при изменениях, которые добавляют новые возможности, но при этом не ломают то, что есть. Таким образом, если человек использует мой модуль, то при выпуске новой версии, например

он может обновиться и его текущий код не должен сломаться.
И наконец мажорная — MAJOR версия. Если я внес хоть какое то, минимальное изменение, которое ломает существующий код, например поменял порядок аргументов у функции, то я обязан изменить MAJOR версию

Вот такая, достаточно простая схема нумерации версий, у нее есть еще ряд нюансов и если захотите с ними подробней ознакомиться — http://semver.org/lang/ru/ Семантическое версионирование, используется повсеместно в Node.JS и не только.
Для его, чтобы поставить конкретную версию используют вот такой синтаксис

Например 3.0 — это последняя версия ветки 3.0 например 3.0.15. Могу просто указать 3 — тогда это последняя версия этой ветки, если последняя была 3.8.6, то поставила бы ее. Обычно старую версию ставят либо из соображений совместимости, либо потому что у более новой какие то ошибки.

Иногда возникает другая задача, необходимо поставить самую, самую последнюю версию модуля, которая еще не была опубликована.  Например, потому что в ней были исправлены важные ошибки или добавлены какие то возможности. Это очень просто, если модуль разрабатывается используя систему версионирования «Git». Например на GitHub. Достаточно получить Git Read-Only url

Screenshot_08_02

скопировать его и в консоли набираем

получаем

Screenshot_08_03

Эффект то же. Еще один вариант, это прямо скачать архив с модулем и дать его аргументом в «npm i …» более подробно про «npm install» можно посмотреть в хелпе —

Screenshot_08_04

Откроется документация в браузере

Screenshot_08_05

как видите, перед нами список всего, что может получать эта команда. То есть «npm install» очень гибкая штука, она может ставить модуль от куда  угодно.

следующие поля информационные, это
(6)  «author» — про автора
(10) «contributors» — про тех кто принимал участие
(40) «license» — понятно,
(41) «repository» — это репозиторий где находятся исходники модуля, информационное поле, никакой существенной роли не играет
(45) «homepage» — говорит само за себя
(46) «keywords» — ключевые слова — информационное поле, которое используется «npm search» при поиске.

(57) «dependencies» — уже структурное поле, оно указывает те модули от которых зависит данный. Если мы обратим внимание на консоль, то там, когда ставился «express», выдало вот такой список

Screenshot_08_06

Это подмодули. Каждый модуль из этого списка будет ставиться в поддиректорию «node_modules». То есть видите, я поставил «express» в папку с проектом, и «NPM» сам создал себе папку «node_modules» куда и поставил «express». Внутри же папки «express» есть своя папка «node_modules» где и находятся подмодули «express».

Screenshot_08_07

Это очень классное свойство «NPM».

Свойство «dependencies», можно использовать, так  же для упрощения установки модуля. Например я  написал модуль и я хочу его кому нибудь передать. Не обязательно при помощи репозитория, или я его куда нибудь скопировал, я не обязан таскать за собой большую директорию «node_modules», я просто сделаю

и дальше, кто угодно, кто получил директорию с «package.json» может зайти в консоль и набрать команду «npm i»

Screenshot_08_08

Как видите, «NPM» сначала выругался на мой «package.json», в связи с недостатком описания, но потом, все же, поставил «express» в директорию «node_modules», причем «express» именно версии 3.

Screenshot_08_09

Кроме «dependencies» есть еще «devDependencies»
(85) «devDependencies» — они не ставятся, если модуль подтягивается как зависимость. Иначе говоря, в той инсталляции которую я только что сделал, через «npm install» в «express» поставились только «dependencies». Модули «devDependencies», предполагается, что нужны для разработки и они будут ставиться в двух случаях. Первое — если стоит специальный флаг конфига, команда есть такая «npm config». И второе, если я зайду непосредственно в директорию «express» и уже в директории из консоли наберу «npm install»

Screenshot_08_10

(114) «scripts» — позволяет задавать команды которые автоматически выполняются при некоторых действиях с пакетом. Со списком таких команд можно ознакомиться введя в консоли «npm help scripts».

Так же бывает поле «main» — оно задает точку входа в пакет. Обычно, когда мы подключаем какой то модуль, например «require(«express»)», то подключается файл «index.js» в этой директории. Заданием поля «name» это можно поменять, например

В таком случае при подключении «require(«express»)» будет подключаться не «index.js» которого может и не быть, а данный файл «application.js».

Ну и многие другие поля с которыми можно ознакомится в документации по «package.json» или, введя в консоли «npm help json», все в той же документации.

7. Введение в NPM — менеджер пакетов для Node.JS

Всем привет! Эта статья посвящена «NPM». Менеджеру пакетов для Node.JS. Модуль «NPM» идет вместе со стандартной инсталляцией Node.JS. Если вы поставили Node.JS то «NPM» вы поставили тоже. И в этом модуле, кроме всего прочего содержится консольная утилита которая дает доступ к громадной базе данных модулей, поддерживаемых сообществом. Сейчас на главном сайте «NPM» — www.npmjs.com, как они пишут, более четверти миллиона модулей. Это достаточно много, с одной стороны, с другой стороны, это не о чем, поскольку многие модули давно заброшены и не разрабатываются. Но даже если их вычесть, все равно полезных модулей очень много и как правило, если стандартная программистская задача, то модуль для ее решения мы можем найти. Это первое, что вообще надо сделать, поискать готовый модуль.

Сейчас нашей задачей будет понять, что же такое эти самые пакеты с которыми работает «NPM». Для этого мы сейчас познакомимся с программистом, которого зовут Константин. Константин сидит за своим компьютером и только что он создал замечательный модуль. Назвал его «supermodule». Константин хотел бы поделиться этим модулем с другими людьми, конечно же используя «NPM». Для этого Константину не достаточно просто создать директорию с модулем, нужно еще создать для них специальный файл, описание пакета. С названием «package.json». Этот файл содержит самую главную информацию о том, что за пакет здесь находится.

«name : supermodule » как правило «name» совпадает с названием директории и версия здесь самая, что ни на есть первая. Если Константин достаточно ленив, то он может не создавать «package.json» руками а воспользоваться вызовом «npm init» из консоли. «npm init» спросит основные характеристики пакета и их надо будет ввести или пропустить.

Screenshot_7_01

И с генерирует «package.json». Основные поля это

 

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

Screenshot_7_021

Итак «package.json» готов и можно опубликовать модуль в центральной базе данных. Для этого существует команда «npm publish» если сейчас ее вызвать то будет ошибка, потому что, чтобы ее опубликовать нужен юзер. По этому Константин набирает «npm adduser» и создает юзера отвечая на появляющиеся поля. NPM отправляет соответствующие запросы и вожделенного юзера Константин получил.

Screenshot_7_03

Теперь вся работа с «NPM» будет от имени этого юзера. Это конечно же имеет значение только если Константин как то работает на изменение в центральной базе данных. Для установки модуля это не нужно, а вот для публикации как раз очень даже важно.

Давайте себе представим, что нас отвлекли и мы отложили публикацию нашего модуля на завтра. Завтра мы возвращаемся в нашу директорию «supermodule» с намерением опубликовать его. Юзера то мы вчера уже создали, нам соответственно надо залогиниться. Очень просто, вводим команду «npm login» далее свой username и password и email.  И вот мы снова здесь. Со списком команд вы можете ознакомится введя команду «npm help».

Возвращаемся к Константину. Вводим «npm publish», он делает запрос к базе данных и отправляет в базу модуль Константина. И что же мы видим

Screenshot_7_04

В чём дело? Почему не работает? Давайте разбираться! Читаем внимательно, говорит, может я не залогинен, хм… Давайте проверим — вводим «npm whoami»

Screenshot_7_05

Всё верно, это я. Ну все ясно, оказывается до нас, некий Илья уже создал модуль с таким названием. Ну конечно же двух модулей с одинаковыми названиями быть не может в одной базе данных «NPM», иначе получилась бы полная неразбериха. Заходим в файл описания пакета, даем новое имя нашему модулю меняя «name : supermodule» на «name : supermodule1234567», пробуем

Screenshot_7_06

 

Ура! Отлично, модуль создан, теперь кто угодно может его поставить, ну а Константин, конечно же если он залогинен, может вносить в него изменения.

А в это время, где то далеко, далеко сидит Петя. Петя пишет проект и в этом проекте ему нужен модуль, который ну просто супер. Петя хочет его найти в базе данных «NPM» и он пишет в консоле «npm search super module» или просто «npm s super module».  «npm search» подтягивает изменения в базе данных в локальный кеш и потом делает поиск. В данном случае в качестве супер модуля вот сколько всего нашлось и конечно нашелся наш модуль «supermodule1234567»

Screenshot_7_07

Петя решил, что хочет поставить именно его. Петя вводит команду «npm install supermodule1234567″ или просто «npm i supermodule1234567». «NPM» скачивает модуль

Screenshot_7_08

Скачивает он его в директорию «node_modules» если ее не существует, то «NPM» её создаёт. В Петином проекте теперь появилась директория «node_modules» и в ней находится супер модуль от Константина. И теперь, конечно, Петя может сделать «require(‘supermodule1234567)»

Screenshot_7_09

И запускаем

Screenshot_7_10

Отлично, вот модуль и пригодился. Обратим внимание на небольшую тонкость, связанную с местом установки модуля. Вернемся в консоль и видите, тут в конце вывода «npm install supermodule1234567» написано куда поставился модуль

Screenshot_7_11

Например Петя сделал директорию «db» и перешел в эту директорию. И захотел поставить какой то модуль в ней. И он вводит «npm install supermodule1234567» и что же произойдет? Модуль поставиться не в ту же директорию из которой Петя вызвал  «npm install»  а в директорию выше, где у нас находится папка «node_modules». Так происходит потому, что модули ставятся по следующему принципу. А именно «NPM» ищет директорию «node_modules» или файл «package.json» в текущей директории, если не находит, ищет на уровень выше, и выше, аж пока не найдет и поставит туда. И вот если не найдет ни директорию «node_modules» ни файл «package.json», только тогда «NPM» сам создаст папку в текущей директории. Смысл в том, что «NPM» таким образом ищет корень пакета, чтоб разместить там нужный нам модуль и как правило именно такое поведение и является желательным.  Ну а что если я все таки хочу поставить модуль в папку «db», очень просто, достаточно «node_modules» руками создать и вызвать находясь в этой директории «npm install».

Со временем Константин выпустит новый модуль. Для того чтобы Пети обновить этот модуль из репозитория, достаточно выполнить команду «npm update» и «npm» обновит все модули находящиеся в директории «node_modules», если их авторы выпустили новые версии. Ну и наконец, если Пете надоело использовать наш супер модуль, он может удалить его из директории «node_modules» руками или использовать команду «npm remove supermodule1234567″ или «npm r supermodule1234567».

Итак мы рассмотрели основной жизненный цикл пакета «NPM».

Основные команды NPM

Жирным выделены короткие варианты команд, можно вводить и так и так.

  • npm init ->  создает package.json
  • npm adduser -> создает пользователя, регистрация своего профиля в NPM
  • npm publish -> публикация пакета в центральной базе данных NPM, ее так же называют репозиторием.
  • npm search -> команда, для поиска пакета.
  • npm install -> поставит модуль по названию.
  • npm update -> обновит модуль по названию, если вызвать без имени модуля, она обновит все модули что есть.
  • npm remove -> удалить модуль по названию.
  • npm help -> позволяет получать встроенный help npm.

Иногда в «npm help» достаточно интересные вещи, например если посмотреть «npm help search» то тебя кидает на локальную доку и тут есть такая информация, что можно искать не просто по ключевым словам, а и по регулярным выражениям.

И на конец, еще одно небольшое дополнение по базе данных по репозиторию. Центральный репозиторий  находится по адресу https://registry.npmjs.org » это база данных в системе CouchDB в которой содержится как раз мета информация про модули. То есть например я захожу «https://registry.npmjs.org/имя_моего_модуля» и здесь содержится информация о модуле, информация из его «package.json» и ссылка на файл с модулем, этот файл тоже находится в базе, он был загружен туда автоматически в процессе выполнения команды «npm publish». Обращаю внимание, все, что загружено в репозиторий является публичным и  открыто для всех. Ну а что если мы работаем в компании которая не может, прямо таки все публиковать открыто и при этом мы хотим использовать «NPM», чтобы внутри компании удобно работать с пакетами? Для этого мы можем поднять свой собственный, корпоративный «NPM» репозиторий и уже работать с ним. На этом мы заканчиваем с общей информацией по «NPM». Дальше мы будем более глубоко изучать «package.json» и пользоваться модулями из этого хранилища.

6. Приёмы работы с модулями

Объект module

Нашей следующей темой будет изучение объекта «module». Объект «module» это основополагающий объект в понимании модулей. В нем есть множество важных свойств которые нам понадобятся в более сложных сценариях поведения, к которым мы скоро с вами перейдем.

Объект «module» является переменной которая существует в каждом модуле, выведем ее в консоль:

Screenshot_6_01

Переменная модуль, есть в каждом файле и содержит информацию об объекте данного модуля, который по мере того как Node.JS обрабатывает файл постепенно заполняется. Кратко пройдемся по его основным свойствам. Давайте для наглядности скопируем вывод модуля вот сюда:

Итак:

  1. «id» как правило содержит полный путь к файлу. Если операционная система поддерживает символические ссылки и файловая система их поддерживает конечно же, то все символические ссылки будут здесь отображены. Если вы являетесь пользователем Windows и не знаете, что такое символические ссылки, то ничего страшного, для понимания это не критично. «id»  используется внутри Node.JS. Как правило мы сами его использовать не будем.
  2. «exports» мы уже знаем. Это экспорты того, что выдается наружу.
  3. «prent» Это ссылка на родительский модуль, то есть на тот модуль который required данный.
  4. «filename» Имя файла, полное, с учетом пути.
  5. «loaded» Загрузился ли модуль. На момент, когда мы выводим в консоль модуль, этот модуль еще до конца не обработан, файл то не выполнен до конца, поэтому «loaded: false».
  6. «children» Это соответственно те модули, которые данный модуль подключил, через «require()». В данном случае тут только один модуль, наш «ru.json», который, обратите внимание, «loaded: true».
  7. «path:» Это тоже внутренняя переменная как и «id» и мы ее не будем использовать, я скажу о ней несколько слов, позже, когда мы будем разбирать порядок поиска модулей с учетом путей.

Из этого обширного списка нам важны два свойства, которые на практике используются наиболее часто. Это свойство «parent» и «exports», по этому о них мы в дальнейшем поговорим более подробно.

Модуль или приложение? module.parent

Первый, можно сказать разминочный прием который мы с вами обсудим, это использование «module.parent». Бывает так, что какой то JS файл, может работать как в режиме прямого запуска, через Node, как например «node server.js», так и в качестве модуля, для чего то другого.

Например модуль «server.js» будет запускать свой функционал, только в том случае, если он запущен явно. А если нет, если какой то другой модуль его подключил? То пусть он этот функционал экспортирует. Разделить эти два случая можно при помощи проверки.

Если «module.parent» есть? это означает, что «server.js» кто то подключил в этом случае имеет смысл экспортировать весь функционал например заключив его в функцию «run()»

и сделаем

А если «module.parent» отсутствует и результат проверки «false»? Это означает, что сервер запущен сам по себе. В этом случае давайте запустим эту функцию прямо сейчас

Приведем «server.js» целиком

Проверяем, пока что работает?

Screenshot_6_02

Работает! Сработала «else».

Давайте сделаем новый модуль и назовем его «app.js». Подключу в нем сервер и запустим его

Теперь запустим «app.js» командой «node app.js»

Screenshot_6_03

Отлично, наша проверка сработала, определила наличие «module.parent», соответственно поместила функцию «run()» в «exports», тем самым позволило ее вызвать в «app.js».

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

Модуль-функция
module.exports = function

Следующий прием по работе с модулями который мы изучим касается правильного использования «module.exports».

Когда мы записываем свойства в «exports», для того, чтобы вынести из модуля, на самом деле мы пишем их в «module.exports». «module.exports» это и есть то самое истинное свойство объекта «module» которое наружу выходит. А «exports» и «this», в контексте модуля, являются ссылками на него.

По этому я могу написать

и могу написать

разницы не будет. Могу написать полностью

Обычно используют

по двум причинам:

  1. Это короче чем «module.exports».
  2. «this» еще короче, но «this» менее универсален. Потому что «this» на уровне модуля это то же самое, что «exports», а вот «this» функции уже будет другим. По этому для унификации  используют везде обычно «exports», если нет какой то особой причины использовать «module.exports».

А какая эта особая причина? если мы внимательно посмотрим сейчас на наш код:

то тут мы видим некую несуразность. Мы на самом деле из модуля «user/index.js» хотим наружу выдать только функцию «function User(name)». Мы не хотим выдать что то еще  и по этому объект здесь не нужен. Нам бы хотелось так:

Получили функцию и использовали, без всякого промежуточного объекта. Это возможно если в «user/index.js» вместо

записать вот так напрямую:

То есть экспортируемый объект как раз и будет наша функция «User()». Обратите внимание, именно так как написано выше. Записать вот так вот:

было бы не возможно, это не работает. Потому что смотрите, у нас есть «module.exports», а «exports» это всего лишь ссылка на него. Если заменить эту ссылку, то на «module.exports» это не повлияет. Так работают объекты в JavaScript — если я меняю что то по ссылке, то оно изменится здесь внутри объекта. А если я заменяю саму ссылку то ничего не произойдет с другими ссылками. Итак проверяем:

Screenshot_6_04

Все хорошо, наш код стал еще проще.

Кеширование модулей

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

База данных будет файлом «db.js», создадим его. И в нем у нас для базы данных прямой кандидат, это наши фразы в «ru.js». По этому давайте лучше создадим каталог «db», поместим туда «db.js» и переименуем его в «idex.js». Туда же поместим и «ru.json». Наша структура проекта имеет следующий вид:
Screenshot_6_05 У объекта базы есть метод «connect» и при вызове этого метода пусть она загружает фразы. Сейчас это просто так, а конечно же, в реальной жизни, это будет подсоединение к базе данных из которой потом можно делать запросы. Запросы как «getPhrase». Этот метод будет возвращать соответствующую фразу, а если ее нету, то выдавать ошибку. Вот так выглядит код «db/index.js» целиком:

Теперь меняем меняем «user/index.js»:

Что мы здесь поменяли? В первой строке подключили файл базы, во второй создали коннект (такие правила работы с базой) и в восьмой строке вместо «phrases.Hello» теперь соответственно вызываем метод «db.getPhrase(«Hello»)». Запускаем:

Screenshot_6_06

А теперь, так как эта база данных глобальная для нашего проекта, давайте я ей воспользуюсь и в сервере тоже. Подключу объект базы в «server.js». И выведу «console.log(db.getPhrase(«Run successful»));» наш «server.js» теперь имеет такой вид:

Изменим «ru.json», добавив еще одну фразу:

И теперь несколько слов о том как это все будет работать.
Когда Node.JS первый раз загружает модуль, в файле «server.js»( на первой строке), он полностью создает соответствующий объект «module», с учетом «parent», «exports» и аналогичных свойств.  И запоминает его у себя. «module.id», тот самый который обычно является полным путем к файлу, служит идентификатором для внутреннего кеша. Node.JS как бы запоминает файл такой то для него создан объект модуль такой то. И в следующий раз, когда мы получаем тот же файл в «user/index.js», получается, что и в «server.js» и в «user/index.js» будет использован один и тот же объект базы данных который мы запрашиваем в «require()».  Соответственно прием здесь такой — первый раз когда подключается модуль(в файле «server.js») он инициализуется и мы вызываем «db.connect()». Теперь «server.js» выглядит так

В дальнейшем в «user/index.js» он уже инициализован поэтому мы просто его берем и пользуемся.

Расположение модулей: порядок поиска

А теперь сделаем следующий логический шаг. Дело в том что в «server.js» мы «db» получаем из текущей директории, а в «user/index.js» из родительской. Давайте подумаем что будет когда мы разовьем «user» и у него появятся поддиректории. Сейчас мы вызываем «db» вот так

из поддиректории будем вот так

а если я буду переносить файлы, то мне нужно следить, чтоб пути правильно обновлялись. Вот и вопрос, как бы нам сделать такую штуку, чтоб «db» подключалась просто вот так:

Зачем мне указывать явно путь к базе, если мы знаем, что имеется ввиду одна база которая в корне, главная. Для того чтоб так сделать — «var db = require(‘db’);» нам нужно понимать порядок поиска модулей в Node.JS. Для этого обратимся к документации. Заходим в Google и ищем «node module» и первая же ссылка даст нам документацию «https://nodejs.org/api/modules.html» по модулям в Node.JS. В дальнейшем я буду, по возможности, именно, комментировать документацию которая уже есть, разъяснять всякие тонкие моменты нежели, чем писать какие то свои выводы, просто потому, что в документации все равно нужно ориентироваться, ее нужно понимать. В данном случае здесь есть описание ряда свойств о которых мы говорили. Нас интересует порядок поиска. Вот он:

Screenshot_6_07

Переходим, видим:

Screenshot_6_08

Это то, что происходит когда вызывается «require()». Скорее всего, если вы видите это в первый раз, то не очень понятно, я постараюсь разъяснить. Итак, «require()» модуль. Вообще в Node.JS есть много встроенных модулей, например модуль по работе с файловой системой «fs». И если это, такой, встроенный модуль, то «require(‘fs’);» сработает тут же и все готово. Как описано  в нашем изображении, вариант номер один.

Дальше, если я указал путь к «require(./..)» — вариант номер два:

В данном случае это «./db». Тогда Node.js поищет файл по этому пути, попытается либо найти данный файл как указано здесь

Либо, затем он попытается получить данный файл как директорию.

Здесь есть упоминание  о «pakage.json», LOAD_AS_DIRECTORY(X)/пункт 1, мы об этом позже поговорим. В нашем случае он возьмет «db/index.js», LOAD_AS_DIRECTORY(X)/пункт 3. Это и будет файлом модуля.

Ну и на конец, третий пункт.

Третий сработает по вышеизложенному алгоритму, в том случае если я  путь не указал и при этом это не встроенный модуль. Тогда Node.JS будет его искать. Есть специальное название директории которое называется «node_modules» из

И он поищет эту директорию, сначала в текущем местоположении.  То есть если мы вызываем из «server.js»  изменим его так

то Node.JS будет искать папку «node_modules», чтоб в ней найти «db». Искать ее он будет сначала в своей директории, потом на уровень выше и выше и выше, пока не найдет. На первом же совпадении поиск остановится. Помните мы смотрели такую штуку «module path». «module path» это как раз те пути по которым он будет искать. Иначе говоря это просто текущий путь и все выше него. Это нужно для того, чтоб можно было создать директорию «node_modules» и в нее поместить внешние модули и они были бы доступны просто по «require(‘module_name’)».  Директорий «node_modules» может быть несколько. Первая в которой будет найден «module_name» послужит точкой остановки поиска.

Таким образом я могу в «server.js» использовать такой путь «require(‘db’)»  если «db» есть в «node_modules». Давайте проверим.

Screenshot_6_09

 

Работает! Поехали дальше!
А что если я не хочу помещать свой «db» в «node_modules»? «db» итак директория, зачем ее помещать в еще одну директорию, не к чему. Хочу просто в корень проекта кинуть «db» и чтоб работало. Можно и так! Потому что после того как Node.JS поищет все эти «node_modules» и ничего не найдет node использует еще одно место для поиска. Это переменная «NODE_PATH».

Screenshot_6_10

В «NODE_PATH» можно указать еще несколько путей по которым еще будет искать. Давайте вернем директорию «db» в корень проекта и запустим «server.js», предварительно установив переменную окружения «NODE_PATH=.» при помощи команды «set» в Windows.

Screenshot_6_12

Все хорошо, потому что «.». то есть текущий путь добавился в список тех, по которым происходит поиск.

И наконец, кроме «NODE_PATH», по историческим причинам, происходит поиск еще в таких директориях

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

Ну и наконец следующий прием который мы с вами рассмотрим называется «Модуль-фабрика».

Передаем параметры: модуль-фабрика

Мы посмотрим этот прием на практическом примере, а именно в процессе подключения логгера к нашему приложению.

Логгер, это отдельный модуль который мы назовем «logger.js». Создадим такой файл в корне нашего проекта. Мы пока в этот файл ничего записывать не будем, а сосредоточимся на том, что нужно для того чтоб им пользоваться. А именно изменим наш «user/index.js»

Что мы здесь изменили? Ну первое мы в строке два создали переменную «log» и присвоили ей объект модуля «logger.js» вернув его через «require(‘logger’)». Мы хотим что? Мы хотим когда я вызываю в строке восемь «log(db.getPhrase(«Hello») + «, » + who.name)» то выводилась в консоль соответствующая строка, как и прежде, но перед ней было бы название модуля который ее вызывает. Соответственно, чтоб логгер выводил мне название текущего модуля мне нужно текущий модуль ему передать. Давайте я это сделаю

Патерн модуль фабрика заключается в том, что я подключаю модуль — «require(‘logger’)» и тут же передаю ему параметры. — «(module)» Параметры при подключении я не могу передать как либо иначе чем

Давайте заполним «logger.js» и вы поймете как это работает, если уже не догадались:

Сначала я делаю «module.exports» равно фабричная функция которая получает название модуля который нужно логгировать — «function(module)» и которая исходя из этого модуля делает «функцию логгер». Эта функция она, что делает, она получает какие то параметры — «function(/*…*/)» и давайте она будет передавать их в «console.log.apply(console, arguments);», конечно она может их и в базу выводить или в файл или куда угодно. И давайте не просто их передадим, а кое что еще добавим. Делаем из «arguments» обычный массив — «var args = [].slice.call(arguments)»  и прибавляем ему «[module.filename]» получается

вот сначала мы прибавили имя файла и предали все аргументы в косоль

Что ж, давайте проверим, работает ли оно

Screenshot_6_13

Как видим каждый модуль теперь выведен. «index.js» скзал «Привет, Петя», а «server.js» сказал «Запуск успешен».
В дальнейшем мы поговорим о уже готовых логгерах, которые можно поставить и использовать.

Итого на этом занятии мы поговорили о различных приемах работы с модулями.

  • Объект module. О том что такое объект module
  • Модуль или приложение? module.parent Как запустить модуль в различных режимах. Приложения или компонента.
  • Модуль-функция module.exports=function. Как экспортировать то что нам надо, а не обязательно объект.
  • Кеширование модулей. Подключаем модуль, один раз инициализуем и в дальнейшем пользуемся уже объектом. То есть заново файл модуля никогда не читается. Хотя существуют такие команды которые позволяют сделать пустым кеш Node.JS, то есть убрать модуль из кеша. Можно поэкспериментировать, если хотите, в документации есть информация на этот счет, но обычно этого никто не делает. И именно это кеширование помогает избежать глобальных переменных.
  • Расположение модулей: порядок поиска. Если мы хотим, чтобы модуль у нас был глобальным, то есть искался без пути, то он должен быть в «node_modules» либо по «NODE_PATH» должен искаться.
  • Передаем параметры: модуль-фабрика. Как реализуется передача параметров в модули, при помощи модуль-фабрики.

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

5. Модули для Node.JS

Всем привет, на этом занятии мы создадим наш первый проект на Node.JS. Нашей основной целью при создании этого проекта будет знакомство с модулями, способами которые Node.JS предлагает для организации проекта. И начнем мы с того, что откроем WebStorm или ваш любимый редактор в новой пустой директории «start». В этой директории будет находится проект Node.JS. Так как я использую WebStorm, то мне так же понадобится небольшая инициализация. Запускаем WebStorm > File > Settings… > (в левой колонке) Languages & Frameworks > Node.js and NPM  > ( в правой части окна) Coding Assistance > Node.js Core library is not enabled > Жмем кнопку «Enable».

Screenshot_5_1

По умолчанию WebStorm считает, что я редактирую обычный html, обычный браузерный JS и он мне будет предлагать варианты автодополнения соответствующие браузерному скрипту, а мне нужны именно Node.JS. По этому я жму кнопку «Usage scope», которая появилась на месте «Enable». В появившемся окошке выделяем строку с названием проекта и кликаем по списку подключенных библиотек, он(список) находится на пересечении строки названия проекта и столбца с названием «Library»

Screenshot_5_2

Теперь в выпавшем списке кликаем по Clear, так мы очистили список подключенных библиотек, теперь можем добавлять нужные нам библиотеки отметив их галочками, со всеми ними мы в дальнейшем познакомимся.  К стати сейчас мы редактируем список библиотек на уровне проекта, но можем и на уровне отдельной папки кликнув на пересечении названия этой папки и столбца «Library» и выбрав библиотеки из списка. Screenshot_5_3

И так, мы добавили библиотеку «Node.JS Core» для всего проекта. Инициализация завершена.

Создаем первый файл, этот файл будет называться «server.js». Для этого правой кнопкой мыши кликаем по названию проекта,

Screenshot_5_4в выпадающем окне наводим на New далее кликаем по File. В появившемся окошке вводим название будущего файла с разрешением «server.js».

 

 

Целью этого занятия является знакомство с модулями, по этому я буду писать простой JavaScript.

Я добавлю в этот файл объект «User», который будет создавать пользователей. У пользователей могут быть конечно же методы например «hello» где «(who)» это другой User. Далее создаем двух пользователей и запускаем наш код вызвав метод «hello» у одного из пользователей и передав ему другого пользователя в качестве аргумента.

Вспоминаем, мы уже рассматривали как открыть окно команд в нужной нам папке. Открываем его в папке с проектом и водим следующую команду: C:\start>node server.js

Screenshot_5_5

Отлично работает, начало положено. Теперь представим себе, что мы развиваем наш проект дальше. «User», это достаточно мощный объект и там может быть много всего и функции растут. Со временем появляется необходимость вынести этот «User» в отдельный файл. И тут-то в дело вступают модули.

Подключение: require

В браузере, когда мы хотим добавить еще один скрипт на страницу мы используем, как правило тег: <script></script>. В Node.JS для этой же цели мы используем специальную команду: «require» и работает она совсем, совсем по другому. Давайте рассмотрим это на нашем примере.
Для псевдокласса «User» я создам отдельный файл. И перемещу User’а из «server.js» в «user.js». Для того, чтоб нам было удобно, я даже расположу его в отдельной колонке.

Screenshot_5_6

Для того, чтобы из одного файла подключить другой, используется команда:

можно указать расширение «.js», можно не указывать. И чтобы проконтролировать выполнение этой команды, я добавлю в «user.js»:

что ж, запускаем:

Screenshot_5_7

Похоже, что то не так, произошла ошибка! Node.JS не находит здесь переменную User, она не определена.

Screenshot_5_8

И здесь мы видим первое важное отличие системы модулей Node.JS от браузерных скриптов. В браузере, если на странице есть два тега скрипт, соответственно два скрипта, то функция которая определена на глобальном уровне в одном из них доступна и в другом, а в Node.JS не так. В Node.JS каждый модуль или иначе говоря, каждый файл, может определить в себе любые функции, любые переменные. И эти функции и переменные являются глобальными для данного файла, они не становятся доступны автоматически при подключении. Это действительно здорово! Поскольку позволяет писать действительно независимые модули. И не опасаться, что я в одном модуле перезапишу глобальные переменные другого.

Переменная «exports»

Но как же быть в данном случае? Ведь здесь то я как раз хочу, чтоб переменная «User» была доступна в «server.js». Для этого, как правило, используется система экспортов. В каждом модуле есть специальная переменная «exports». Это объект и то, что я туда положу, вернется как результат «require(./someFile.js)». Например, в данном случае:

Screenshot_5_9

Таким образом каждый модуль может объявить свои собственные приватные функции, переменные и то, что он хочет отдать наружу, вот таким образом экспортировать.

Переменная «global»

Может возникнуть резонный вопрос, а что если мы хотим все таки глобальные переменные? Например есть такие объекты как скажем «logger» или «База данных» или какой то глобальный объект приложения, которые мы хотим, чтобы были доступны явно и везде. Без всяких там экспортов, просто потому что они, такие вот важные. На самом деле в Node.JS есть концепция глобальных переменных, но вместо объекта «window», который используется в браузере, используется объект «global».  И то, что мы пишем в этот объект «global», именно то, что записываем явным образом, вот так:

становится глобальной переменной. И если я так написал, то поубирав все лишнее из наших файлов, могу попробовать запустить еще раз.

Screenshot_5_10

О! Работает. Сначала подключился файл «require(./user);», он обработался, «global.User = User;» сработал и  «var = vasya» и «var = petya», у меня глобальные переменные. То есть технически это возможно, однако в Node.JS есть ряд особенностей этой системы модулей, которые мы скоро с вами изучим, которые позволяют обойтись совершенно без глобальных переменных и на практике, этот объект «global» практически не используется. И далее мы будем чувствовать себя комфортно без всяких глобальных переменных.

Итак мы с вами поговорили о том как подключить файл модуля. Мы поговорили о том, что у каждого модуля есть свои собственные переменные и функции, экспортированные и можно, но не нужно делать глобальные. Теперь мы  с вами поговорим о тех видах модулей, которые есть.

Виды модулей: JS, NODE, JSON

То, что мы с вами рассмотрели — тип модуля «JS» (мы ведь подключали «user.js «), это самый часто используемый модуль JavaScript файл. Но есть и другие. Следующий тип  модуля, вы вряд ли сейчас захотите использовать. Этот тип модуля носит расширение «.node» и делается он путем компиляции файла на языке «C++». Как правило, такое делают в тех случаях, когда нужно либо очень хорошая производительность, либо нужно использовать какие то возможности операционной системы, к которым, почему то нельзя, сейчас, обратиться из JavaScrip из Node.JS. И наконец третий тип модуля, это «JSON».

Сейчас я вернул вариант с использованием обычного экспорта вместо глобалов. И допустим я хочу добавить небольшую интернационализацию. Вообще то  для  этого есть множество возможностей, стандартных форматов, модулей уже готовых, но я буду делать все руками. Итак вынесем фразу «Hello», из нашего вывода в консоль

в отдельный файл, который будет хранить соответствия английских фраз и фраз на соответствующем языке.

Создаем новый файл с названием «ru.json». Этот файл будет хранить соответствия, например:

Именно формат Json нужен, то есть если бы я записал вот так:

Это было бы не правильно. Формат Json требует обязательного указания кавычек, это не JavaScript объект, это формат.
И теперь в user.js я просто пишу:

Могу указать расширение, могу не указывать. Если Node.JS не находит файл «ru.js» он ищет файл «ru.json». Загружает его, интерпретирует и получившийся объект будет хранить в «var phrases». Что ж проверим:

Screenshot_5_11

Отлично, все еще работает!
Модули в формате «.json» используйте в тех случаях когда хочется хранить какие-то данные в простейшем виде, в виде файлов.

Модуль-директория DIR/index

Теперь мы будем дальше развивать проект и вместе с файлом «user.js» нам для реализации функционала «Юзера» понадобятся еще  какие-то файлы. При этом будет целесообразно выделить модуль в отдельную директорию. Создадим директорию с именем «user».

Screenshot_5_12

Screenshot_5_13

Screenshot_5_14

Директории тоже можно подключать. При этом Node.JS сначала ищет файл с таким названием «user.js» потом «user.json» если он не находит ни того ни того, он ищет директорию с названием «user». И в этой директории хочет взять файл «index.соответствующее расширение», считает его модулем. Соответственно я «user.js» перетаскиваю в директорию «user»(в WebStorm перемещение файла из директории в директорию можно совершить простым перетаскиванием, зажав левую кнопку мыши) и называю его «index.js».  К нему же и положу наш «ru.json». Для того, чтоб переименовать файл «user.js», после его перемещения, надо кликнуть левой кнопкой мыши по файлу, в выпадающем меню выбрать пункт «Refactor» и выбрать «rename». В появившемся окне изменяем название файла на «index.js». Проверяем — Все работает.  Теперь, если мне понадобятся дополнительные файлы для реализации функционала «Юзера», то я смогу добавить их в эту директорию.

Далее приведу наш рабочий код:

Итак мы с вами знаем:

  • Что такое модуль, фактически это файл, который подключается при помощи «require( )».
  • Мы знаем какие виды переменных есть в модуле: exports и global
  • Какие виды модулей существуют: JS, NODE, JSON
  • Так же мы знаем, как организовать модуль в виде директории

В следующей части мы продолжим с этим работать, более глубоко изучим объект модуля и различные приемы его использования.

4. Исходники и документация.

Практически все готово, чтобы двигаться дальше, но перед этим желательно зайти в раздел «downloads», на сайте https://nodejs.org и скачать исходный код Node.JS. Зачем это нужно? Node.JS содержит в себе как код на С++ так и JavaScript код для встроенных модулей. Многие встроенные модули написаны на JavaScript и потом, используя возможности V8, скомпилированы уже в выполняемые файлы и слинкованы с Node.JS. Для нас это не так важно, мы здесь  с С++ разбираться не будем, но если мы хотим залезть внутрь встроенных модулей, а нам иногда нужно будет это делать, чтоб понять как оно работает, то нужно эти встроенные модули скачать.

Screenshot_4_2

И разархивировать. Из под Windows, для разархивации, я воспользовался 7-Zip. Пришлось разархивировать дважды, сначала из «node-v4.4.7.tar.gz» у меня получился «node-v4.4.7.tar», потом уже просто папка с исходниками.

Итак, открываем исходники, заходим в директорию «lib», и вот эти файлы.

Screenshot_4_3

Обращаю ваше внимание, если вы просто поставили Node.JS из пакета, уже скомпилированный, готовый, в том числе и под Windows, то этих файлов не будет, и залезть например внутрь модуля «http.js», посмотреть что тут как происходит,  вы не сможете.

Screenshot_4_4

Впрочем, вы можете это сделать не сейчас, а потом, когда нам это действительно понадобится.

Документация.

Несколько слов по документации. Документацией мы будем пользоваться стандартной, вот она — https://nodejs.org/dist/latest-v4.x/docs/api/
тут достаточно много модулей. Если я хочу что то найти в документации, я обычно ищу так — Google -> nodejs console

Screenshot_4_5

Как видите первая же ссылка ведет нас на документацию. Переходите по ней и получаете необходимую информацию. На что хотелось бы обратить особое внимание, перейдя по ссылке вы обнаружите отдельную плашечку «Stability».

Screenshot_4_6

В Node.JS есть модули с различным уровнем готовности. Условно говоря от 0 до 3. Об этом можно почитать вот здесь About these Docs

Screenshot_4_7

Смысл такой, что 0 значит, что этот модуль не стоит использовать, а дальше от 1 до 3 различные степени стабильности. И фишка здесь в том, что стабильность, например «Experimental», то есть низкая, она не означает, что модуль плохо работает. Модули с такой стабильностью, могут работать замечательно, без единой ошибки. Стабильность означает лишь то, что API этого модуля, то есть набор функций, методов может в дальнейшем изменится. Соответственно использовать методы нестабильные можно, но стоит иметь ввиду, что они могут поменяться в будущем. При этом работать они могут вполне хорошо. Вот пожалуй все, что хотелось сейчас сказать про документацию. В дальнейшем мы будем к ней неоднократно  обращаться по мере углубления в разработку и изучение Node.JS.

3. Установка и запуск

http://nodejs.org

Ну что, время завязывать со всякой нудной теорией и переходить к практике. Сейчас мы посмотрим как установить Node.JS, как на нем выполнять скрипты и немножко залезем в документацию. Для этого я первым делом зайду на сайт http://nodejs.org. Здесь есть такая большая кнопка, которая, как правило, позволяет скачать пакет наиболее подходящий для вашей ОС. Вначале посмотрим, что с Mac OS. С Mac OS все просто, мы жмем на кнопку, скачиваем «node-v4.4.7.pkg», запускаем его, все подтверждаем, все очень очевидно, мы не будем это рассматривать, ошибиться тут не возможно.

Следующее это Linux. С Linux все чуть сложнее, потому что в Linux обычно есть различные пакеты, но в пакетах не самая новая версия, а при работе с Node.JS лучше использовать последние версии, если нет каких-то особых причин так не делать. Так что если вы ставите из пакета, то убедитесь, что версия именно последняя. Если у вас пакет устарел, то Node.JS замечательно компилируется из исходников. Для этого можно загуглить «nodejs linux» в первых пяти ссылках обязательно будет инструкция по установке. Можете загуглить установку под какую то определенную систему например «node.js debian» и вы тоже находите инструкцию на первой же странице. Если вы пользуетесь Linux, то этот процесс не составит для вас особого труда.

Ну и наконец Windows. нажимаем на кнопку и скачиваем «node-v4.4.7-x64.msi» —

Screenshot_3_1

после того как он скачался, запускаю и соглашаюсь со всем, что предложит операционная система, все по умолчанию. Отлично Node.JS установился. Установился он в C:\Program Files\nodejs и тут есть как файл node.exe так и npm.cmd. NPM это пакетный менеджер мы рассмотрим его немножко позже.

Screenshott_3_2

Node.JS когда ставится прописывает себя в переменную PATH. Чтобы в этом удостовериться можете проделать следующее — в Windows 10 нажимаете правой кнопкой мыши на значок  «windows», который некогда был «пуск». В появившемся окне выбираем «система»

Screenshot_3_3далее жмем на «Дополнительные параметры системы», потом «переменные среды.

Screenshot_3_4Screenshot_3_5

 

 

 

Перед нами появилось окно «переменные среды» в котором нас интересует записи в среду PATH. Причем не важно для всех пользователей или для вашего пользователя (в нижнем окне или в верхнем) главное, что присутствуют записи «C:\Users\ASUS\AppData\Roaming\npm»  и «C:\Program Files\nodejs\». Теперь проверим работает ли Node.JS в принципе. Для этого в любой папке или на «Рабочем столе» при зажатой клавише «Shift» нажимаем правую кнопку мыши и выбираем «Открыть окно команд» такой трюк позволяет нам открыть консоль с прописанным путем в ту папку в которой мы нажали правую кнопку мыши. Другой способ открыть консоль через меню «пуск». Нажимаем правой кнопкой мыши меню «пуск», выбираем «Командная строка».

Screenshot_3_8

Screenshot_3_9

 

 

 

 

 

 

Итак мы запустили консоль. Вводим команду «node» и у нас появляется приглашение ввести javascript выражение. Это так называемый режим «repl» когда можно вводить javascript выражения и они выполняются.

Screenshot_3_10

Дважды нажав сочетание клавиш «Ctrl + c» мы выходим из этого режима. Вообще этот режим используется достаточно редко, здесь мы его используем просто, чтоб проверить, что установка прошла успешно. Конечно же такой запуск должен работать не только в «Windows», а и из любой операционной системы.

Как правила под Node.JS запускают файлы. Например создадим файл «1.js» и запишем в нем команду:

она сделает то же самое, что делает в браузере. В консоли  вводим команду «node 1.js» и жмем «Enter»:

Screenshot_3_11

Обратите внимание в  консоли прописан путь в ту папку, в которой у нас находится наш файл 1.js (в моем случае это рабочий стол).

Если у вас это работает, поздравляю, вы запустили свой первый скрипт под Node.JS!

 

2. Что такое Node.JS? Почему Node.JS?

 

Что такое Node.JS?

 

Создан Ryan Dahl в 2009.

А теперь мы поговорим о том, что такое Node.JS. Node.JS — это программное средство для выполнения JavaScript.  То есть ставится Node.JS и Node.JS выполняет JavaScript на сервере, на десктопе, на ноутбуке, на мобильных устройствах и так далее. JavaScript где угодно. Node.js был создан Райаном Далом в 2009 году.

Node.JS = V8 + I/O + библиотеки

Что же такое сделал Райан и почему Node.JS получил такое большое признание? Ведь на самом деле до Node.JS существовали другие попытки сделать то же самое. Node.JS создан на основе виртуальной машины V8. Эта виртуальная машина была создана компанией Google для браузера Chrome и она умеет выполнять JavaScript.

V8: быстро, современно, экономно

Не просто умеет, она делает это очень хорошо. Она выполняет JavaScript быстро, она поддерживает практически все возможности современного JavaScript, самого современного стандарта который сейчас принят, плюс можно при помощи специальных флагов включить возможности будущего стандарта. Кроме того  V8 очень экономно расходует память, очень хорошо оптимизирована в этом плане, позволяет профилировать процессор, память, смотреть, что происходит. Очень, очень хорошая штука!

Альтернативы: Rhino, JSC, WSH…

Альтернативы V8 которые есть, а они существуют, это Rhino — на основе Java, Java Script Core — который используется в частности в Safari в Mac OS, Windows Script Host — который есть в Windows. То есть другие способы выполнять JavaScript на сервере. На любом компьютере их можно поставить, но они уступают V8 в скорости, в эффективности расходования памяти. По этому V8 в данном случае безусловно плюс. Но V8 это JavaScript, V8 не умеет читать файлы, не умеет работать с сетью и так далее. По этому Райан добавил при помощи специальных библиотек и конечно же своего кода возможности по работе с сетью, с файлами, с потоками ввода/вывода и некоторыми другими. То что получилось в результате, позволяет делать из JavaScript — Web сервер.

Почему Node.JS?

Что интересного может быть для нас в Node.JS как технологии, почему мы можем захотеть Node.JS.
Для этого есть ряд причин:

  1. Хочу JavaScript! Если вы хорошо знаете JavaScript зачем изучать другой язык? Будем использовать его и на клиенте и на сервере.
  2. Общий код на клиенте и на сервере. Значить мы можем использовать одинаковый код, ту же библиотеку и на клиенте и на сервере. Впрочем на практике это повторное использование весьма ограничено и оно обычно касается библиотек общего вида. Допустим есть объект «User». Этот объект «User» в браузере делает одно, использует возможности браузера, а на сервере он обычно делает другое, в том числе работает с базами данных, тут уже вообще другой код. То есть прямо таки разделяемого кода не так много, но тем не менее он есть.
  3. Решает основные задачи для Web.  Node.JS предназначен для решения основных задач, которые перед нами ставит Web разработка. Хотим работать с базой данных, легко — Node.JS отлично работает с самыми распространенными современными базами данных. Хотим получить низкоуровневый доступ к сети http, https, tcp, udp, в Node.JS содержится отлично проработанная коллекция модулей. Node.JS Это инструмент который изначально проектировался для решения задач под Web и в нем очень много этого сделано. С другой стороны Node.JS наверно не самый лучший если вы хотите создать оконное приложение под Windows или посчитать число Пи с точностью до какого то n-го знака. В этом случае наверно будут более предпочтительны другие инструменты. Node.JS это средство которое решает основные задачи под Web и делает это хорошо.
  4. Много соединений и задач одновременно. Node.JS лучше всего себя ведет там, где нужно поддерживать большое количество соединений. Например это 10 000 клиентов в чате одновременно или это онлайн игра, где тоже очень много игроков одновременно подключены и что то делают. Большое количество соединений, задач это то с чем Node.JS справляется хорошо. При этом эти задачи не должны быть вычислительными. Хотя если задачи вычислительные то в Node.JS есть средства для параллелизации, но они не так хорошо проработаны как на некоторых других платформах.
  5. Легко сделать рабочий прототип. Следующее, это рабочий прототип. На Node.JS очень легко создать, что то готовое и заставить это работать, причем работать в том числе под нагрузкой. Когда мы разрабатываем, то современные методики разработки итеративны. То есть мы делаем что то, оно должно работать, потом мы добавляем к этому фичи, она опять работает, потом мы добавляем что то еще и так. И на Node.JS первый этап проходит очень быстро, а если все в порядке с архитектурой, то и дальше оно отлично расширяется.
  6. Удобный менеджер пакетов, где много всего. В Node.JS есть очень удобный менеджер пакетов, NPM, мы его подробно рассмотрим и есть очень много готовых пакетов, которые можно поставить и работать с ними.
  7. Большое и активное сообщество вокруг. Ну и наконец, сообщество. Есть много, много людей которые любят Node.JS, которые пишут под Node.JS, которые поддерживают то, что они сделали под Node.JS. Преимущественно это индивидуальные разработчики или небольшие компании плюс сообщество. По этому такая ситуация складывается, что есть очень много готовых пакетов, модулей которые нужно поставить и они вместе нормально работают. Для приложений на Node.JS, совершенно нормально если они используют двадцать, тридцать, пятьдесят, восемьдесят готовых модулей даже.  Такая вот матричная структура получается, когда есть много, много маленьких модулей которые вместе интегрируются и отлично работают, благодаря тому, что Node.JS предоставляет для этого Framework.

1. Введения в node.js

 

О чем эта книга.

Всем привет, эта книга посвящена веб серверу Node.JS. В ней мы будем говорить о том, что нужно для создания веб приложений, сайтов, сервисов Node.JS. Мы не будем разбирать все, что связано с сервером Node.JS,  этого очень много, но все самое главное, самое важное для создания сервисов, веб приложения мы разберем достаточно подробно. Чтобы вы не только понимали как это делается, но и понимали, почему оно работает, как там, что внутри устроено в этом сервере и что делать если почему то у вас, что то, не работает.

Окружение.

Перед тем как мы перейдем собственно к серверу Node.JS, несколько слов об окружении для разработки. Здесь я работаю на операционной системе windows

Внимание, здесь первое различие между текстом скринкаста и данной книгой. В оригинале «MAC OS», но у автора блога, увы, «windows». Так как текст будет дополнятся скринами с реальной обстановки, все уроки будут адаптированы под «Windows». Где будет необходимо, будут даны пояснения для других ОС.

— однако у вас все должно замечательно работать в том числе под «Linux», «Mac OS». Там где есть существенные различия, я постараюсь остановиться подробнее.

Программы которые я буду использовать:
Терминал, под Mac это iterm, а под Windows это просто обычная командная строка либо файловый менеджер.
Редактор WebStorm.
Редактор Sublime Text 2.
Браузер Google Chrome.

WebStorm я использую с плагином, плагин называется NodeJS.
Запускаем WebStorm > File > Settings… > (в левой колонке) Plugins.

Screenshot_1_1

Если у вас еще нет его, то нажимаем Browse repositories…  находим его в списке и вставляем. Потом конфигурируем его —
File > Settings… > (в левой колонке в пункте) Languages & Frameworks > (ищем подпункт) Node.js and NPM > (в правой части окна нажимаем) Configure…

Screenshot_1_2
IDE скачает исходники на ваш компьютер.
Это нужно для того, чтобы нормально работало авто дополнение для встроенных модулей.

!!! Делать это нужно только после установки самого Node.JS, которую мы разберем чуть позже.