Друзья, поздравляем всех с окончанием рабочей недели! Подготовили для вас на выходные интересный перевод, приуроченный к запуску новой группы по курсу «Разработчик JavaScript».

Как известно, Node.js – это отличный инструмент разработки под Web.
Его история начинается в 2009 году, когда Райан Дахл создал серверную JavaScript платформу. Набор встроенных библиотек и архитектура, основанная на цикле событий (Event Loop architecture) стала довольно привычной для JS разработчиков и позволила им использовать свои навыки для разработки различного рода приложений, начиная от написания простых скриптов и веб-серверов до технологии Интернета Вещей и практик машинного обучения.



NodeJS широко используется с интерфейсом командной строки CLI. В статье мы рассмотрим ключевые аспекты построения программ с помощью CLI. Начнем мы с теории, дальше разберемся с NPM и package.json, а также реализуем маленькое приложение на JavaScript с использованием базовых опций.

Почему CLI?

CLI – это программа, в которой пользователь взаимодействует с терминалом. Инструменты командной строки чаще всего используются разработчиками, связанными с интернет-технологиями – программными инженерами, DevOps, системными администраторами. Основная цель CLI – автоматизировать различные задачи и инкапсулировать сложные операции в маленькие команды.

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

С помощью Node.js процесс создания CLI приложения становится быстрым и легким по многим причинам. Начнем с JavaScript. Он является одним из самых популярных языков программирования в мире. Он буквально везде – в браузере, на стороне сервера, в облаке. Динамическая типизация JavaScript упрощает создание расширяемых проектов и открывает возможность для создания плагинов.

Еще одно преимущество создания CLI приложений с помощью технологии Node.js – это NPM (Node.js package manager), отличный встроенный инструментарий, который позволяет организовывать код по пакетам. Гигантское сообщество позволяет выбирать и использовать библиотеки, написанные для абсолютно разных целей. Например, закон Этвуда гласит, что
«Любое приложение, которое может быть написано на JavaScript, будет написано на JavaScript.»

Развитая инфраструктура модулей позволяет разработчикам фокусироваться на логике приложений и делает Node.js хорошим инструментом для прототипирования, что является важным достоинством, поскольку time to market (TTM) величина является крайне критичной.

Обзор базовых принципов

Чтобы понять базовые принципы, концепции и перенять лучшие практики, давайте для начала взглянем на инструменты, которыми JavaScript разработчики пользуются в повседневной жизни. Один из уже упомянутых популярных инструментов в Node.js – это NPM. Если вы напишете npm в командной строке, то вы увидите справочное сообщение.



NPM показывает возможные для выполнений команды и базовую информацию о программе. Заметьте, что сообщения выводятся без указания на то, что надо делать именно так, а не иначе. Это поведение по умолчанию, когда нет никаких входных значений. Оно делает доступной команду help. Чтобы она также стала предиктивной, стоит включить опцию –help без строго фиксированного синтаксиса.

npm --help
npm -h
npm help
npm

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

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



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

Давайте напишем требования для дальнейшей разработки с помощью Gherkin нотации, позже нам это пригодится.

When a user enters "my-cli" program with "help" option (or without arguments)
Then it shows a help message about the program

Следующая вещь, которую можно заметить в справочном сообщении NPM сверху, это то, что в нем в нижней части выводится версия.
npm@6.4.1
Это еще одна полезная практика CLI, которая позволяет пользователю понять, как использовать инструмент и не зайти в тупик из-за неожиданного поведения программы. Обычно, чтобы решить проблему или попросить помощи, пользователь ищет ответ в интернете (например, на Stack Overflow). Может быть не совсем ясно, почему тот или иной ответ не работает. Именно понимание текущей версии дает возможность работать с актуальным программным обеспечением. Опция –version оправдает ожидания пользователей при использовании того или иного сценария.

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

When user enters "my-cli" program with "version" option
Then it shows the actual program's version

Ваш первый CLI

Мы собираемся работать с командной оболочкой Linux для написания своей первой CLI программы. Базовые примеры также будут работать на Mac OS. Нам нужно, чтобы на машине был установлен Node.js. На этом этапе его версия не так важна, но мы будем использовать Long Term Support (LTS), а именно 10 версии.



NPM не ставится отдельно, он идет вместе с Node.js. Первый шаг – представить приложение, над которым мы работаем.

mkdir my-cli    # create the project's directory
cd my-cli       # go to new location 
npm init --yes  # initialise NPM package
echo "console.log('Hello, world!')" > server.js   # create hello world example
npm start       # run the script

С помощью этих команд мы создали простейшее приложение на Node.js. Во каждой из них мы использовали различные инструменты командной строки, такие как mkdir, cd, echo и, наконец, npm. При запуске последней команды мы должны увидеть следующее



Наша цель сейчас – создать что-нибудь очень простое, а уже в следующих туториалах мы разработаем достаточно мощные инструменты.

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

git init    # initialise Git repository
git add .   # add new files
git commit -m "Initial Commit"  # save the state

Созданный код достаточно далек от понятия CLI. Мы запустим это с помощью команды npm во время инициализации, а также по некоторым причинам мы можем использовать node.

В этом NPM действительно хорош. Давайте добавим свойство bin в файл package.json.

gist.github.com/korzio/08dc4fcecda0e2c1f9b3f8592807edca#file-medium-basic-npm-help-js

Свойство bin при условии того, что пакет установлен, сигнализирует NPM, что команда с именем пакета должна быть добавлена в PATH. После установки пакета глобально.

npm install?-?global 

Становится возможным запустить команду my-cli в терминале в любой директории. NPM сделал файл server.js исполняемым. Нормальная установка положит bin файл в директорию node_modules/.bin проекта и включит запуск ее с помощью команды npx. При запуске команды npm link мы создадим символьную ссылку на пакет и упростим процесс разработки и дебага.

my-cli
/Users/Alex/.nvm/versions/node/v10.11.0/bin/my-cli: line 1: syntax error near unexpected token `'Hello, World!''
/Users/Alex/.nvm/versions/node/v10.11.0/bin/my-cli: line 1: `console.log('Hello, World!')

В любом случае, вывод – это не желаемая “Hello, World!” строка, поскольку *nix системы интерпретируют исполняемый файл с помощью sh. Чтобы файл был интерпретирован с помощью node необходимо добавить шебанг в начало файла server.js.

#!/usr/bin/env node
console.log('Hello, World!')

Теперь my-cli выведет “Hello, World!”, как и предполагалось. А теперь самое время разработать version и help поведения.

Мы не хотим много раз дублировать информацию в разных местах, поэтому используем поля файла package.json — name, version, description, как единственный источник правдивой информации для программы.

"name": "my-cli",
"version": "1.0.0",
"description": "My First Node.js CLI",

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

#!/usr/bin/env node
const { description, name, version } = require('./package.json')

const VERSION_MESSAGE = `${name} ${version}`
const HELP_MESSAGE = `${VERSION_MESSAGE}
${description}
Usage: 
--help    Help documentation
--version Installed package version`

console.log(HELP_MESSAGE)

Последнее парсит полученные аргументы в качестве опций и решает, какие значения показывать. Мы будем использовать глобальную переменную процесса (global variable process) в среде Node.js и ее свойство process.argv, argv в массиве, где первый элемент – это путь к версии файла запуска Node.js, а второй – пусть к программе. Дальше передаются через пробел все аргументы. Их можно увидеть с помощью добавления выражения console.log(process.argv).

При запуске в
my-cli test=me option
Вывод будет следующим

my-cli@1.0.0
My First Node.js CLI

Usage:
--help    Help documentation
--version Installed package version
[ '/Users/Alex/.nvm/versions/node/v10.11.0/bin/node',
  '/Users/Alex/.nvm/versions/node/v10.11.0/bin/my-cli',
  'test=me',
  'option' ]

Помните о том, что мы решили выводить версию программы, если ее версия подходящая.

When user enters "my-cli" program with "version" option
Then it shows the actual program's version

Далее представлен код, реализующий это требование

#!/usr/bin/env node
const { description, name, version } = require('./package.json')

const options = process.argv.slice(2)
const VERSION_MESSAGE = `${name} ${version}`
const HELP_MESSAGE = `${VERSION_MESSAGE}
${description}
Usage: 
--help    Help documentation
--version Installed package version`

if (options.includes('--version')) {
  console.log(VERSION_MESSAGE)
} else {
  console.log(HELP_MESSAGE)
}

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

When a user enters "my-cli" program with "help" option (or without arguments).

Then it shows a help message about the program

В этой статье мы рассмотрели базовые аспекты построения CLI в Node.js. Мы взглянули на дефолтный вывод команд NPM и git, написали небольшую программу на JavaScript, которая выводит сообщения справки и сведения о версии. В следующей части мы рассмотрим спектр существующих инструментов и библиотек и продолжим создание приложения интерфейса командной строки.

Эта статья является частью цикла «Crafting Notes CLI in TypeScript», а все туториалы предоставлены JavaScript Planet – группой программных инженеров, наставников и сетевых специалистов. Наша цель – помочь разработчикам получить новые знания и улучшить навыки программирования.

Вот такой вышел материал. Пишите комментарии и не забывайте о том, что 18 марта состоится бесплатный открытый вебинар с разработчиком JavaScript в международной финансовой корпорации ING — Александром Коржиковым.

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


  1. i8008
    15.03.2019 23:21
    +1

    #!/usr/bin/env node
    console.log('Hello, World!')

    Это боль. Пишем консольное приложение (CLI®) для *nix … на ноде… Вот прям самый простой и логичный подход. Жду продолжения в стиле «написание модулей ядра на связке jQuery + Electron»