По опыту знаю: первый шаг нового проекта, например, создания модуля или средства командной строки, заключается в настройке рабочего окружения. Некоторым этот шаг нравится, некоторые его терпеть не могут, но и у тех и у других предварительная подготовка часто занимает непозволительно много времени. Особенно, когда надо всё тщательно проверить и заставить все механизмы слаженно и стабильно работать вместе.
Конечно, можно включить в арсенал JS-разработчика webpack, eslint, jasmine, или даже TypeScript. При таком подходе с нахождением и устранением ошибок проблем не будет. Но всё дело в том, что для решения большинства вспомогательных задач прекрасно подойдут простые инструменты, которые практически не нуждаются в настройке. Окружение, собранное из них, позволит максимально быстро начать работу, обеспечит контроль правильности кода и своевременное оповещение об ошибках.
Когда я задумываюсь о минимальном JS-окружении, на ум сразу приходят четыре вещи: тестирование программы и анализ кода, отслеживание изменений файлов в процессе работы и проверка проекта перед фиксацией транзакций в системе контроля версий.
Сейчас я подробно расскажу о том, как, буквально на пустом месте, создать среду разработки, которая позволит в считанные минуты приступить к продуктивному труду.
Инициализация проекта Node.js и Git-репозитория
Сначала создадим директорию и перейдём в неё. Здесь конструкция
$_
хранит аргумент последней команды.$ mkdir awesome-module && cd $_
Теперь инициализируем проект Node.js с настройками по умолчанию.
npm init --yes
Создадим папки и файлы
$ mkdir lib test
$ touch index.js lib/meaningOfLife.js test/index.test.js test/meaningOfLife.test.js
Теперь инициализируем Git-репозиторий и зафиксируем первую транзакцию.
$ git init
$ git add -A; git commit -am "Awesome Module, day one"
Структуру проекта мы подготовили, займёмся инструментами.
Установка инструментов
Мы будем использовать четыре простых модуля, каждый из которых предназначен для решения одной задачи:
- Ava – тестирование.
- Standard – статический анализ кода.
- Chokidar-cli – наблюдение за изменениями в файлах.
- Precommit-hook – автоматический запуск npm-скриптов.
Почему я выбрал именно их? Просто потому, что они не требуют вообще никакой настройки. Такой подход отлично разгружает голову, открывая дорогу полезным идеям, касающимся разработки. Установим модули, выполнив следующую команду в папке проекта:
$ npm i --save-dev ava standard chokidar-cli precommit-hook
После установки (скорость которой зависит только от настроения NPM), не забудьте создать файл
.gitignore
и добавить в него папку node_modules
. Она в репозитории не нужна.Настройка проекта
Сами по себе, наши инструменты в настройке не нуждаются, но вот проект, всё же, настроить придётся. Правда, здесь всё предельно просто. Откройте
package.json
и добавьте в него следующие скрипты:"scripts": {
"test": "ava",
"lint": "standard",
"dev": "chokidar '**/*.js' -c 'standard && ava'"
},
"pre-commit": ["test", "lint"],
Вот, собственно, и всё. Как только вы выполнит команду
npm run dev
, chokidar
начнёт наблюдать за состоянием файлов, запуская, при необходимости, standard
для статического анализа, и ava
для тестирования кода. Если обнаружатся проблемы, вы тут же об этом узнаете. То же самое касается и внесения изменений в репозиторий. Наша среда не даст зафиксировать транзакцию до тех пор, пока проект не будет успешно проанализирован и протестирован.Здесь хотелось бы обратить внимание на две вещи.
- Не нужно устанавливать
standard
илиava
глобально, так как они исполняются изнутри контекстаnode
.
- Так как мы используем
&&
вместо;
в скриптеdev
, тесты не будут вызваны до тех пор, пока код не пройдёт проверку статическим анализатором. Это ускоряет работу.
Как этим пользоваться
Среда разработки рассчитана на программирование в стиле разработки через тестирование (TDD). Как только будет запущен скрипт
dev
, можно создавать тесты, они будут автоматически добавляться к набору испытаний кода, без необходимости перезапуска средства наблюдения за файлами или выполнения любых других операций.Создадим первый тест.
// test/meaningOfLife.test.js
const test = require('ava')
const meaningOfLife = require('../lib/meaningOfLife')
test('Real meaning of life', (t) => {
t.is(meaningOfLife(), 42)
})
После сохранения этого файла система тут же сообщит о том, что один из тестов провален. Исправим это.
// lib/meaningOfLife.js
module.exports = () => 42
Теперь всё работает как надо! Проще некуда. Создадим модуль, который умножает числовые параметры. Сразу же подготовим модульный тест для него, а также посмотрим, правильно ли работает новый модуль с
meaningOfLife
. Это, кстати, будет уже интеграционный, а не модульный тест. Вот код модуля:// lib/multiply.js
module.exports = (number) => {
if (typeof number !== 'number') throw new TypeError('Only numbers can be multiplied!')
return number * 2
}
Вот тест к нему:
// test/multiply.test.js
const test = require('ava')
const multiply = require('../lib/multiply')
test('Can multiply numbers', (t) => {
t.is(multiply(10), 20)
})
test('Throws when you try to multiply non-number value', (t) => {
t.throws(() => multiply('ohai!'), 'Only numbers can be multiplied!')
})
Теперь протестируем всё вместе:
// test/index.test.js
const test = require('ava')
const awesomeModule = require('../index')
test('Works nicely together', (t) => {
t.is(awesomeModule(), 84)
})
И внесём следующее в index.js:
// index.js
const meaningOfLife = require('./lib/meaningOfLife')
const multiply = require('./lib/multiply')
module.exports = () => multiply(meaningOfLife())
Тесты пройдены! Как видите, благодаря простоте инструментов, мы очень быстро приступили к работе над проектом, потратив совсем немного времени на подготовку окружения.
Итоги
Новые сверкающие инструменты часто буквально гипнотизируют программистов, заставляя забыть о главном. А главное – это упрощение и ускорение работы и борьба с ошибками. Обычно, гораздо чаще, чем может показаться, для решения этих задач достаточно самых простых средств. Таких, которые позволяют тратить время на создание программ, а не на настройку вспомогательных систем.
Когда проект начнёт расти, возможно, вы почувствуете, что вам нужно что-нибудь гораздо более продвинутое, нежели простая комбинация ava, standard, chokidar-cli и precommit-hook. Но в большинстве случаев, однако, больше ничего не понадобится. И те простые и понятные инструменты, о которых я рассказал, прослужат вам верой и правдой очень и очень долго.
А в какой среде создаёте программы вы?
Комментарии (9)
impwx
09.12.2016 15:26+2if (typeof number !== 'number') throw new TypeError('Only numbers can be multiplied!')
Вместо того, чтобы обмазывать такими проверками весь код, а потом еще писать тесты на эти проверки, лучше сразу использовать Typescript.
Apathetic
09.12.2016 22:13+2standard?
Спасибо, нет. В нем противно решительно всё, начиная от двух пробелов для интендации и запрета на точку с запятой (Крокфорд, где ты, когда ты так нужен?) и заканчивая довольно-таки наглым самоименованием. Стандарт? Ха, нет.DAiMor
10.12.2016 14:01Ну и в дополнение Standard не статический анализатор кода, как пишет автор, это просто style guide, да и только.
YU76
17.12.2016 16:02Ну вот я не могу въехать во все это сразу, т.к. работаю на C# и считаю, что нужно расширять стек используемых технологий. Но на строке с командой npm напрочь перестаю понимать, что происходит.
Думаю, всем присутствующим это не составляет проблем, и понимаю почему. А с другой стороны — поставьте себя на мое место.
Прикладная разработка внутри компании, TFS, C#, WCF, WPF и несколько разработчиков.
Ну телепатом надо стать, чтобы понять, куда копать.
Может Вы вкратце укажете, куда смотреть, чтобы понять смысл команд и используемых инструментов? Буду очень признателен.
И не я один такой.
Гуглил уже до потери сознания, но все воедино не могу сложить никак…
MrCheater
У меня насчёт AVA вопрос:
Предположим, что у меня есть такой код:
Этот код работает только благодаря loader-ам Webpack-а. Чем AVA лучше Mocha, если без компиляции кода теста, тест всё равно не завести?
Semigradsky
AVA внутри использует Babel. Просто дбавьте в конфиг плагины/пресеты, которые вам нужны.
В данном случае вам нужен пресет react.
MrCheater
Не-не-не. Babel тут не причем. Babel не умеет CSS-Modules, SVG и прочие клевые штуки. Это задача webpack-loaders и webpack-plugins.
dex157
Если перед тестами каждый раз собирать проект с webpack, то достаточно много времени уходит на запуск тестов, в нашем проекте мы используем такие хаки
в таком случае mocha/wallaby.js могут собирать проект и не ругаться на файлы ассетов