Вокруг полно JavaScript-фреймворков, библиотек и разнообразных инструментов. Что выбрать? Глядя на такое разнообразие, разработчику непросто ответить на этот вопрос.

image

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

Конечно, можно включить в арсенал 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 для тестирования кода. Если обнаружатся проблемы, вы тут же об этом узнаете. То же самое касается и внесения изменений в репозиторий. Наша среда не даст зафиксировать транзакцию до тех пор, пока проект не будет успешно проанализирован и протестирован.

Здесь хотелось бы обратить внимание на две вещи.

  1. Не нужно устанавливать standard или ava глобально, так как они исполняются изнутри контекста node.

  2. Так как мы используем && вместо ; в скрипте 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)


  1. MrCheater
    09.12.2016 15:24
    +1

    У меня насчёт AVA вопрос:


    Предположим, что у меня есть такой код:


    import React from 'react';
    import styles from './ExampleComponent.css';
    import DemoIMG from '../assets/logo.png';
    import DemoSVG from '../assets/dummy.svg';
    
    export class ExampleComponent extends React.Component {
        render () {
            return (
                <div className = {styles['root']}>
                    <img src = {process.env.CDN_ROOT_URL + '/image.jpg'}
                    <img src = {DemoIMG}/>
                    <DemoSVG width = {300} height = {300} className = {styles['normal']} />
                </div>
            );
        }
    }

    Этот код работает только благодаря loader-ам Webpack-а. Чем AVA лучше Mocha, если без компиляции кода теста, тест всё равно не завести?


    1. Semigradsky
      09.12.2016 17:52

      AVA внутри использует Babel. Просто дбавьте в конфиг плагины/пресеты, которые вам нужны.

      В данном случае вам нужен пресет react.


      1. MrCheater
        09.12.2016 17:58
        +1

        Не-не-не. Babel тут не причем. Babel не умеет CSS-Modules, SVG и прочие клевые штуки. Это задача webpack-loaders и webpack-plugins.


        1. dex157
          09.12.2016 23:44
          +1

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

          styleHook({
            extensions: [ '.css', '.scss' ],
            preprocessCss: data => sass.renderSync({ data, includePaths: ['./src/theme/'] }).css
          });
          
          require.extensions['.png'] = () => ({});
          require.extensions['.svg'] = () => ({});
          
          


          в таком случае mocha/wallaby.js могут собирать проект и не ругаться на файлы ассетов


  1. impwx
    09.12.2016 15:26
    +2

    if (typeof number !== 'number') throw new TypeError('Only numbers can be multiplied!')
    

    Вместо того, чтобы обмазывать такими проверками весь код, а потом еще писать тесты на эти проверки, лучше сразу использовать Typescript.


  1. RinatMullayanov
    09.12.2016 20:22

    Пробовали husky для Git-хуков?


  1. Apathetic
    09.12.2016 22:13
    +2

    standard?
    Спасибо, нет. В нем противно решительно всё, начиная от двух пробелов для интендации и запрета на точку с запятой (Крокфорд, где ты, когда ты так нужен?) и заканчивая довольно-таки наглым самоименованием. Стандарт? Ха, нет.


    1. DAiMor
      10.12.2016 14:01

      Ну и в дополнение Standard не статический анализатор кода, как пишет автор, это просто style guide, да и только.


  1. YU76
    17.12.2016 16:02

    Ну вот я не могу въехать во все это сразу, т.к. работаю на C# и считаю, что нужно расширять стек используемых технологий. Но на строке с командой npm напрочь перестаю понимать, что происходит.
    Думаю, всем присутствующим это не составляет проблем, и понимаю почему. А с другой стороны — поставьте себя на мое место.
    Прикладная разработка внутри компании, TFS, C#, WCF, WPF и несколько разработчиков.
    Ну телепатом надо стать, чтобы понять, куда копать.
    Может Вы вкратце укажете, куда смотреть, чтобы понять смысл команд и используемых инструментов? Буду очень признателен.
    И не я один такой.
    Гуглил уже до потери сознания, но все воедино не могу сложить никак…