My name is Vasyl Khrystiuk‎ > ‎pub‎ > ‎JavaScript‎ > ‎

node js building with npmjs (analog of java's maven)

Tags: javascript_tag, nodejs_tag




Теория и размышления

    Сборщики проектов очень важны при создании программ. Они находят, если надо - скачивают, подключают зависимости, если надо, компилируют и упаковывают сам проект, занимаются его дистрибуцией - и все в автоматическом режиме. Большинство из них имеет систему плагинов, которые умеют автоматизировать практически любые рутинные действия с проектом.
    Будучи изначально программистом на java, я очень люблю maven(на самом деле это нечто больше чем просто "сборщик"). И хотя у меня с ним много проблем в плане настройки, но все же он делает очень много работы вместо меня и без него я вряд ли мог бы сделать то же самое. Потому я, как любитель яваскрипта и заинтересовался аналогами maven для javascript.
    Вообще существует спецификация сборщиков проектов для javascript (http://wiki.commonjs.org/wiki/Packages/1.0) , которая описывает все(например структуру файла package.json) и которая имеет несколько имплементаций: JSBuildPINF JS Loadernpmjsи т.д.
    Из всего, что я нашел, более удобным мне показался npmjs(Node Package Manager).
    //    Из дополнительных вопросов - возможно ли указывать свои собственные репозитории ?

Скачивание и установка

Для пользователей Windows  - качать отсюда: dist 
В других системах - установка так же как и другой аналогичный софт. 
Установка не имеет ничего сложного, пишу это, чтоб все таки знали, что его всё-таки надо устанавливать.

Пример подключения библиотеки

    Для того, чтоб показать, как подключать библиотеки с помощью npmjs, я создам самый простой проект. Он не будет делать ничего полезного - будет  просто скачивать страницу из интернета и выводить её в консоль. Подключать будем библиотеку request (на самом деле в комплекте с node.js идет нормальный http-клиент, эту же библиотеку я выбрал для демонстрации).

    По порядку:
создадим папку для проекта
>mkdir testapp
>cd testapp

Создадим в папке файл index.js в котором и будет наш скрипт:
var request = require('request');
request('https://en.wikipedia.org/wiki/A_Certain_Scientific_Railgun', function (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body)
  }
})

Если попытаться сейчас запустить этот скрипт:
>node index.js
То мы получим сообщение об ошибке:
module.js:340
    throw err;
          ^
Error: Cannot find module 'request'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (C:\Users\Vasya\testapp\index.js:1:77)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

Что говорит нам о том, что request не подключен. В общем то все верно - мы его пока что не подключали.
Теперь самое время попробовать npmjs в действии.
В этой же папке создадим файл package.json и наполним его всем необходимым:
{
    "name": "testapp",
    "version": "0.0.0",
    "description": "start this",
    "main": "index.js",
    "dependencies": {
        "request": "2.40.0"
    },
    "author": "msangel",
    "license": "Apache-2.0"
}

Внимательно посмотрите на раздел "dependencies" - он то и описывает все библиотеки, какие мы используем и точный номер версии это библиотеки. 
Теперь попробуем установить все:
>npm install
После того, как пакет и все его зависимости сами скачали, тетерь мы можем запустить и сам скрипт:
>node index.js
И в результате у нас на консоль выведется все содержимое статьи на википедии.

Пример подключения библиотеки с нативным модулем (и необходимостью перекомпиляции)

    Иногда библиотеки имеют в себе нативные модули, написанные на с++. Для того, чтоб установить такие библиотеки, в системе нужно иметь компилятор c++ а так же некоторые дополнительные библиотеки для с++.
    Потому тут я расскажу, как установить такой компилятор в Windows 7 и где взять эти дополнительные библиотеки. Для пользователей других операционных систем эта инструкция не нужна - там все делается очень просто и, как правило, в автоматическом режиме. 
    Продолжим работать с нашим тестовым приложением и добавим ему функциональность - на скаченной странице выполним jQuery селектор для получения определенных данных. Для того, чтоб сделать это, нам нужно воспользоваться библиотекой JSDom.
    Потому изменим наш скрипт:
var request = require('request');
request('https://en.wikipedia.org/wiki/A_Certain_Scientific_Railgun', function (error, response, body) {
  if (!error && response.statusCode == 200) {
var jsdom = require("jsdom");
        jsdom.env(body, ["http://code.jquery.com/jquery.js"], function (errors, window) {
        var $ = window.$;
        $("#firstHeading i").each(function() {
            console.log($(this).text())
        });
    })
  }
})

Ну и подключим библиотеку jsdom (изменим файл package.json):
{
    "name": "testapp",
    "version": "0.0.0",
    "description": "start this",
    "main": "index.js",
    "dependencies": {
        "request": "2.40.0",
"jsdom": "0.11.1"
    },
    "author": "msangel",
    "license": "Apache-2.0"
}

Ну и не забудем скачать/подключить новую библиотеку:
>npm install

Однако, если у вас в системе нет компилятора с++ и необходимых библиотек, то вы получите сообщение об ошибке:
    MSBUILD : error MSB3428: Загрузка компонента Visual C++ "VCBuild.exe" невозможна. Способы решения проблемы: 1) установка .NET Framework 2.0 SDK, 2) установка Microsoft Visual Studio 2005 или 3) указание адреса компонента в системном пути, если компонент установлен в другом месте. 


Теперь, когда проблема стала очевидно - я напишу, каким именно образом решал эту проблему я у себя. 

Для решения этой проблемы в систему надо установить:

После того, как компилятор с++ установился, я пересобрал проект:
>npm install
Он успешно пересобрался, необходимые вещи скомпилировались и вот уже можно запустить и попробовать:
>node index.js
A Certain Scientific Railgun


Пару слов еще:
можно билдить с другой версией студии, но для этого надо, чтоб версия студии была корректно прописана в реестре:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows]
"CurrentInstallFolder"="C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1"

Можно попыталься цказать версию явно глобально:
SET VisualStudioVersion=11.0

или так:
set GYP_MSVS_VERSION  = 2010

Самым лучшим решением будет передача версии студии 
npm install --msvs_version=2010
npm install --msvs_version=vs2012

Возможно ли установить С++ компилятор без полного MSVC?

    Может показаться, что для установки компилятора С++ установка всей Microsoft Visual Studio совсем не обязательна. Если кратко - компилятор установить можно, но все равно чего-то будет не хватать(библиотеки, некоторые заглавные файлы и т.д.) и потому проекты не скомпилируются и ничего не будет работать. Подробности ниже. 
    Изначально я хотел все запустить только имея Windows SDK и компилятор С++ но без самой студии(есть такой вариант).
    Но и установка distributable package у меня была проблемной -  он с разу не установился. 
    Говорилось об несовместимости версий, наличии более нового пакета и вообще несовместимости. В поисках проблемы я нашел совет, который мне помог: 
Я скачал этот пакет обновления, но он у меня не запустился, потому что у меня не было в системе Windows SDK 7.1:
    Windows SDK 7.1 not found.
Ну это было не сложно, и я попробовал его скачать:
Установить его, впрочем, я не смог.  У меня была такая ошибка: 
    Installation of the "Microsoft Windows SDK for Windows 7" product has reported the following error: Please refer to Samples\Setup\HTML\ConfigDetails.htm document for further information.

Немного погуглив, я нашел решение: http://stackoverflow.com/a/23032807/449553Нужно просто через панель управления/установка и удаление программ удалить:
        Microsoft Visual C++ 2010 x Redistributable x
    После этого Windows SDK установилось и потом, поверх него, установился и пакет обновления с компиляторами(special set of compiler updates).
    Компилятор установился, но вот многие стандартные библиотеки были недоступными, хотя и были в системе (конфигурировать пути к библиотекам? ок, однако проект для компиляции создается только во время сборки конкретной зависимости, тут же валится и тут же удаляется, обойти это можно, но обходить пришлось бы слишком часто). И потому, уже даже после установки Redistributable Package мне все равно пришлось поставить студию. 


Пару слов о node-webkit

    На сегодняшний день я считаю это самой удобной платформой для создания desktop-приложений. Возможно, кто-то скажет что java/.NOT/c++/python  лучше. Ну, он имеет право. Это всего лишь моя позиция. Плюсы очевидны - низкий порог вхождения, быстрота написания, GUI на основе HTML/CSS/JAVASCRIPT.  
    Да, придется с собой таскать модуль на 20+ мегабайт, но если говорить об аналогах в том же ключе, то и там есть что таскать(пожалуй, исключение только для с++, и то если это какая-то совсем крохотная GUI либа, потому что тот же qt это 14+ мегабайт)
    И еще одно. Я бы пожалуй об этом говорил повсюду, где программируют под GUI. Никогда не работайте с GUI в том же потоке, из которого выполняются тяжелые/блокирующие операции. Изначальная архитектура node.js - асинхронная, но все же, если постараться, то можно совершить и эту ошибку. Для того, чтоб этого избежать есть много средств, например использование node-webworker-threads(или аналогов) для тех самых тяжелых/блокирующих операций.

Пару слов о FFI

FFI(foreign function interface) - это нативная библиотека для node.js, которая позволяет обращаться к библиотекам(как в Windows так и в *nix). 
Так например, можно обратиться к shell32.dll,  зарегистрировать окно и его процедуру обрабоки сообщений и таким образом работать на win32api.
Вот некоторые примеры:
// TBD: Тут может быть пример программы, создающей на win32api окно, добавляющей в него компоненты и реагируующей на действия пользователя. Немного доки:
https://www.google.com.ua/search?q=ассемблер+создать+окно
http://www.codenet.ru/progr/asm/asmwin.php
https://github.com/Benvie/win32-api-js-ffi
https://github.com/Benvie/node-Windows
или даже так(очевидно что этот де модуль используется в других языках для той же задачи, а значит там можно будет подсмотреть примеры):
https://github.com/search?q=ffi+win32api&ref=searchresults&type=Repositories
https://www.google.com.ua/search?q=node+ffi+win32api+examples

И зачем это нужно: имея доступ к win32api, можно строить самые обычные windows-приложения без использования дополнительных GUI библиотек. Т.е. имеем сразу несколько преимуществ - программируем на удобном javascript, используем удобные win32api функции и размер конечной программы малый. 

Особенности сборки для дистрибуции для Windows

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

    Что касается инсталяторов, то есть множество инструментов для этого: NSISмоя любимая inno setup или даже winrar. Не будем на этом заострять сейчас внимания. 

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

    Для разработки на node.js программ с GUI на основе node-webkit, то у node-webkit своя система упакавки, но аналогов которой нет для чистого node.js. Возможно эта система упаковки будет и работать с чистым node.js  Но пихать этот модуль повсюду я бы не стал - он весит от 20 мегабайт и иногда это очень много. Но так как это самый простой способ упаковки, то я написал его первым в очереди, а вы уже думайте. 

    Другой, который мне очень понравился - это "Enigma Virtual Box". Эта софтина пакует приложение и все файлы рядом в один файл, а вызовы к файловой системе из программы перехватывает и если этот запрос - к файлам из архива, то оно аккуратно перенаправляет запрос в нужное место. Из очевидных вещей - все упакованные файлы доступны в режиме read-only, но когда речь идет о модулях для node.js то это именно то, что надо. Вообще, там очень много полезных функций, которые позволяют создать для любой программы песочницу и/или portable-версии. Недостатком является то, что точка входа(сама программа) должна быть exe-формата и ей нельзя добавлять собственные аргументы запуска. Даже вариант с bat-скриптом не сработал. Это оказалось крайне неудобным в случае node.js, но преимущества от использования этой системы настолько велики, что даже написать на с++ небольшой ранер будет оправдано. 

// TBD: Тут может быть ссылка на пример ранера в бинарном формате и в виде исходника

    А еще есть некий "nexe", но на момент написания этих строк у него был один большой недостаток - он не умел работать с native-модулями. 

    А еще, если погуглить, то можно много чего найти - упаковщиков очень много, как специализированных под node, так и общего использования . Я тут написал только то, что мне понравилось и что действительно работает. 


Ссылки

Comments