...

среда, 10 июня 2015 г.

node.js для Java-разработчиков: первые шаги


У опытного программиста, сталкивающегося с новой технологией для решения конкретной прикладной задачи, сразу возникает множество практических вопросов. Как правильно установить платформу? Где и что будет лежать после установки? Как создать каркас проекта, как он будет структурирован? Как разбивать код на модули? Как добавить библиотеку в проект? Где вообще взять готовую библиотеку, которая делает то, что нужно? Как и в чём отлаживать код? Как написать модульный тест?

Ответы на эти вопросы можно при желании легко найти в сети, но придётся перечитать дюжину статей, и на каждый вопрос ответов будет, скорее всего, несколько. Некоторое время назад мне понадобилось написать небольшой туториал по node.js, который бы позволил быстро запустить разработку и познакомить новых программистов в проекте с этой технологией. Рассчитан он на опытных Java-разработчиков, которые и язык JavaScript хорошо знают, но node.js как платформа для бэкэнда для них в новинку.

Думаю, что данная статья будет полезна не только разработчикам из мира Java, но и всем, кто начинает работу с платформой node.js.


Установка и настройка


Установка node и npm

Windows

Установка node.js под Windows производится с помощью msi-инсталлятора. Для его загрузки нужно перейти на сайт https://nodejs.org и щёлкнуть «Install». После скачивания инсталлятора (файл с именем вида node-v0.12.4-install.msi) необходимо запустить его и следовать инструкциям по установке.

По умолчанию под Windows node.js устанавливается в папку c:\Program Files\nodejs. Также по умолчанию устанавливаются все компоненты (собственно node.js, пакетный менеджер npm, ссылка на документацию; кроме того, путь к node и npm прописывается в переменную среды PATH). Желательно убедиться, что все компоненты установки выбраны.

OS X

В OS X проще всего установить node через менеджер пакетов brew. Для этого необходимо выполнить команду:
> brew install node


Node установится в папку /usr/local/Cellar//node с постоянным симлинком /usr/local/opt/node/.
Ubuntu (x64)

Для установки последней ветки (0.12) лучше скачать дистрибутив с сайта:
wget http://ift.tt/1EpwiVr
sudo tar -C /usr/local --strip-components 1 -xzf node-v0.12.4-linux-x64.tar.gz


Дистрибутив распакуется в папку /usr/local в подпапки bin, include, lib и share.
Проверка установки

Для проверки корректности установки можно запустить в командной строке node и npm с параметром --version:
> node --version
v0.12.4
> npm --version
2.10.1


Установка плагина в IntelliJ IDEA

Запустим IntelliJ IDEA, зайдём в настройки.

Найдём раздел Plugins и щёлкнем «Install JetBrains Plugin...»

Найдём в списке плагин NodeJS, щёлкнем по кнопке «Install Plugin». По окончании загрузки кнопка превратится в «Restart IntelliJ IDEA» — щёлкнем её для перезагрузки среды.

После перезагрузки зайдём в настройки и найдём раздел Languages & Frameworks -> Node.js and NPM. Убедимся, что в разделе «Node interpreter» указана ссылка на установленный исполняемый файл node.

В разделе «Sources of node.js Core Modules» щёлкнем кнопку «Configure». В появившемся окне выберем «Download from the Internet» и щёлкнем «Configure», при этом скачаются и проиндексируются исходники node.js. Это позволит просматривать исходники при разработке.

В разделе packages отображаются глобально установленные пакеты (см. раздел «Глобальные пакеты»). В этом окне можно добавлять, удалять и обновлять эти пакеты. Если рядом с именем пакета отображается синяя стрелочка, значит, доступно обновление. Глобально лучше устанавливать только пакеты-утилиты.

Первые шаги


Пишем «Hello World»

Создадим файл app.js, который формирует и выводит соответствующую строчку в консоль:
// файл app.js
var greeting = 'hello';
greeting += ' world!';
console.log(greeting);


Запустим его командой:
> node app.js
hello world!


Используем REPL

Запустив команду node без аргументов, можно попасть в REPL-цикл, аналогичный браузерной JS-консоли. В нём можно выполнять и проверять фрагменты кода:
> node
> console.log(‘hello world!’)
hello world!
undefined

> [1, 2, 3].reduce(function(sum item){return sum + item}, 0)
6


Каждая выполненная строчка имеет возвращаемый результат, который также выводится в консоль. Функция console.log() не возвращает результата, поэтому после её вызова в консоли вывелось «undefined».

В REPL-консоли работает автодополнение по нажатию клавиши Tab. Например, если написать «console.» и нажать Tab, то отобразится список атрибутов и функций объекта console.

> console.
 
console.__defineGetter__      console.__defineSetter__
console.__lookupGetter__      console.__lookupSetter__
console.__proto__             console.constructor
console.hasOwnProperty        console.isPrototypeOf
console.propertyIsEnumerable  console.toLocaleString
console.toString              console.valueOf

console.assert                console.dir
console.error                 console.info
console.log                   console.time
console.timeEnd               console.trace
console.warn
console.Console               console._stderr
console._stdout               console._times


> console.


Для выхода из консоли можно нажать Ctrl+D.

Работа с npm


Инициализация проекта

Для инициализации проекта выполним в каталоге будущего проекта команду npm init и введём необходимые данные в интерактивном режиме (можно просто нажимать Enter, так как предлагаются внятные настройки по умолчанию):
> npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (nodetest)
version: (1.0.0)
description: my first node application
entry point: (index.js) app.js
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to ***\package.json:
 
{  
  "name": "nodetest",  
  "version": "1.0.0",  
  "description": "my first node application",  
  "main": "app.js",  
  "scripts": {   
    "test": "echo \"Error: no test specified\" && exit 1"  
  },  
  "author": "",  
  "license": "ISC" 
}

Is this ok? (yes)


По окончании выполнения утилиты в текущем каталоге будет создан файл package.json, описывающий конфигурацию проекта. В нём же будет храниться информация о зависимостях проекта.
Добавление пакетов-зависимостей в проект

Чтобы установить зависимость в проект, используется команда npm install. При этом в текущем каталоге будет создана папка node_modules, в которую будет помещён загруженный пакет. Ключ --save означает, что информация об этой зависимости будет добавлена также в package.json. Например, установим пакет log4js для протоколирования:
> npm install log4js
log4js@0.6.25 node_modules/log4js
├── async@0.2.10
├── underscore@1.8.2
├── semver@4.3.4
└── readable-stream@1.0.33 (isarray@0.0.1, inherits@2.0.1, string_decoder@0.10.31, core-util-is@1.0.1)


После выполнения этой команды обнаружим, что в текущем каталоге появилась папка node_modules\open, а в файле package.json добавилась запись:
  "dependencies": {
    "log4js": "0.6.25"
  }


Запись о зависимости можно добавить в файл package.json и вручную, но после этого необходимо выполнить npm install, чтобы загрузить указанную зависимость в каталог node_modules.
Глобальные пакеты

Пакеты можно устанавливать как в каталог проекта, так и глобально, тогда они будут видны для всех проектов. Как правило, глобально устанавливаются только пакеты, являющиеся утилитами, например, утилита управления зависимостями bower, сборщики gulp и grunt, генератор проектов на Express express-generator, и т.д.

Глобальные пакеты устанавливаются:

  • В Windows 8 — в %USERPROFILE%\AppData\Roaming\npm\node_modules,
  • В OS X — в /usr/local/lib/node_modules,
  • В Ubuntu — в /usr/local/lib/node_modules.

Чтобы установить пакет глобально, команда npm выполняется с ключом -g:

npm install -g grunt


Работа в IntelliJ IDEA


Открытие проекта

Чтобы открыть проект на node.js, достаточно открыть папку, содержащую package.json.

Настройка конфигурации запуска

Для запуска и отладки в IntelliJ IDEA необходимо создать конфигурацию запуска. Для этого зайдём в Run -> Run Configurations, щёлкнем плюсик в левом верхнем углу и выберем node.js:

Заполним поля Name и JavaScript File:

Теперь можно запускать скрипт в обычном режиме и в режиме отладки с помощью соответствующих кнопок на панели инструментов:

Отладка

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

Модульность в node.js


В Java единицами модульности являются пакеты и классы. Единицей модульности в node.js является файл. Чтобы сделать импорт одного модуля в другой, используется модуль-локальная (т.е. неявно определённая в каждом модуле) функция require(). Стандартные модули или пакеты, установленные в node_modules, можно импортировать по простому имени:
var http = require('http');


В переменную http будет помещён объект, который был экспортирован модулем http.

Если требуется импортировать не стандартный модуль, а один из модулей проекта в другой, то аргумент для функции require() должен содержать размещение модуля относительно текущего модуля (не считая расширения .js), например:

// файл myproject/somedir/mymodule1.js
mymodule2 = require(‘../anotherdir/mymodule2’);
mymodule2.fun();

// файл myproject/anotherdir/mymodule2.js
module.exports.fun = function() {
    console.log(‘hello world!’);
}


Всё, что объявлено в файле модуля, видно только внутри него — за исключением того, что мы явно экспортируем. Например, в отличие от JavaScript в браузере, область видимости переменной, объявленной на верхнем уровне, ограничена тем модулем, в котором она объявлена:
// файл mymodule.js
var enterprise = 'bloody';


Переменная enterprise будет видна только внутри модуля mymodule.js.

Чтобы экспортировать что-либо из модуля, можно использовать доступный в любом модуле атрибут module.exports, который по умолчанию содержит в себе пустой объект. Можно также использовать сокращённую ссылку на него — модуль-локальную переменную exports. Функция require(), которой передано имя нашего модуля, будет возвращать то, что мы поместили в module.exports. Соответственно, если мы поместим туда такой объект:

// файл mymodule.js
module.exports =  {
    fun: function() {
        console.log('hello world!');
    }
}


То именно его вернёт функция require, будучи вызванной в другом модуле:
// файл mymodule-client.js
mymodule = require('./mymodule');
mymodule.fun();


Полученный объект mymodule — это тот же самый объект с функцией fun, который был присвоен атрибуту module.exports в нашем модуле.

Однако подобным способом сделать экспорт не получится:

// файл mymodule.js
exports =  {
    fun: function() {
        console.log('hello world!');
    }
}


Это связано с тем, что из модуля всегда экспортируется атрибут module.exports. Заменив сокращённую ссылку exports на другой объект, мы не изменили этот атрибут. Сокращённая ссылка exports может быть использована только для экспорта каких-то отдельных функций или атрибутов:
// файл mymodule.js
exports.fun = function() {
    console.log('hello world!');
}

// файл mymodule-client.js
require('./mymodule').fun();


Тестирование


Mocha

Для добавления модульного тестирования в проект лучше всего начать с фреймворка Mocha. Устанавливается он как глобальный npm-модуль:
npm install -g mocha


Протестируем модуль с простейшей функцией:
// файл mymodule.js
exports.fun = function(name) {
    return 'Привет, ' + name + '!';
} 


Тесты mocha по умолчанию размещаются в подпапке test:
// файл test/mymodule-test.js
var assert = require('assert');
var mymodule = require('../mymodule');

describe('mymodule', function() {
    describe('#fun()', function() {
        it('должна приветствовать пользователя, имя которого передано как аргумент', function() {
            assert.equal(mymodule.fun('Сергей'), 'Привет, Сергей!');
        });
    });
}); 


Первый аргумент функции describe — это человекочитаемое описание поведения тестируемой функции или модуля, которое будет выводиться в консоль при прогоне тестов. Здесь желательно придерживаться некоторых структурных соглашений — например, в первом describe указывается имя модуля, во вложенном — имя тестируемой функции. Запустим mocha и убедимся, что тест нашей функции проходит:
> mocha

  mymodule
    #fun()
      ✓ должна приветствовать пользователя, имя которого передано как аргумент

  1 passing (7ms)


Использование Mocha в IntelliJ IDEA

Mocha также умеет мониторить исходники и автоматически прогонять тесты при изменении кода. Запустить её в таком режиме можно и из командной строки с помощью параметра запуска --watch, но раз уж мы строим наш рабочий процесс в IntelliJ IDEA, то используем для этого специальную конфигурацию запуска:

В окне настройки конфигурации запуска укажем название этой конфигурации (Name), а также путь к папке с тестами (Test directory). Сохраним конфигурацию.

Изменим код функции так, чтобы он не проходил, и выполним (Run) конфигурацию запуска Mocha.

Теперь щёлкнем кнопку Toggle auto-test в появившейся панели. Эта кнопка включает режим автоматического прогона тестов при изменении исходников.

Исправим код функции, при этом Mocha автоматически прогонит тест и покажет, что теперь всё хорошо:

Ресурсы


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.

Комментариев нет:

Отправить комментарий