Простой и гибкий интерфейс, который избавляет от усталости от JavaScript

В этом посте мы подробнее рассмотрим два новых инструмента в мире интерфейсов. Оба они разработаны с учетом простоты и легкости использования. Первый - это крошечный интерфейсный фреймворк под названием Hyperapp, второй - сборщик ресурсов под названием Parcel. Вместе они могут быть лучшим способом быстро и приятно создать достойное легкое веб-приложение по состоянию на начало 2018 года.

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

Или, говоря словами Хорхе Букарана, автора Hyperapp:

Мне нужно было создать веб-клиент для проекта на работе. Моим первым выбором были React и Redux […], но я хотел что-то легкое и без рамок React.

Гиперапп

Главное преимущество Hyperapp - его размер - около 1 КБ. Пользователи React и Redux будут чувствовать себя как дома с Hyperapp, поскольку это своего рода крошечный React.

Как и React, Hyperapp использует виртуальную модель DOM для вычисления необходимых обновлений модели DOM и следует знакомой абстракции Компоненты и элементы над элементами HTML. Вы даже можете использовать JSX с Hyperapp, чтобы сделать его еще более уютным. Ключевое отличие состоит в том, что компоненты не имеют состояния - для каждого приложения существует только одно глобальное состояние, и все компоненты не имеют состояния.

Управление состоянием Hyperapp основано на Архитектуре Вяза, которая также была основным источником вдохновения для Redux. Понятия неизменного состояния и действий, возвращающих новые объекты состояния, будут знакомы пользователям Redux. Однако нет редукторов, просто действия, которые принимают некоторые аргументы и возвращают новое состояние (хорошо, они могут быть асинхронными и возвращать обещания, но в этом суть ).

Недавно вышла v1, так что самое время уверенно попробовать ее и создать что-то полезное!

"Посылка"

Parcel - новичок в блоке фронтенд-связывания ресурсов. Или, другими словами, своего рода более быстрый и предварительно настроенный веб-пакет. Я большой поклонник webpack, но даже в этом случае должен признать, что настройка немного утомительна. Такая непредубежденность делает конфигурацию прозрачной, но в то же время немного раздутой.

Parcel может похвастаться огромным увеличением скорости по сравнению с webpack и другими сборщиками, а также такими полезными функциями, как горячая замена модулей и разделение кода, которые, конечно же, работают из коробки. К моему удивлению, после связывания .sass файла после запуска сервера разработки участков он автоматически установил node-sass зависимость, а затем преобразовал файл в CSS! Это отличный опыт для разработчиков. О, и это действительно быстро.

PS: Команда Webpack, похоже, поняла намек от Parcel и версия 4 будет включать некоторые разумные значения по умолчанию.

Так как мне его использовать?

Мы напишем простое приложение с использованием Hyperapp & Parcel - оно будет просто извлекать и отображать основные пользовательские данные с помощью GitHub API. Посмотрите на окончательный и аннотированный код в репозитории, ссылка на который приведена ниже 👇, или следуйте инструкциям в этом абзаце.



Удивительное приложение, которое мы собираемся создать:

Начнем с создания нового каталога и установки необходимых зависимостей:

mkdir hyperparcel && cd $_ && npm init -y && npm i hyperapp parcel-bundler babel-plugin-transform-react-jsx babel-preset-env

Наряду с главными героями этого небольшого проекта мы установили два пресета babel, чтобы преобразовать код во что-то понятное для большинства браузеров. Совет: $_ означает «аргумент последней команды».

Теперь продолжаем и добавляем файлы index.html и index.js:

// index.html
<html>
  <body>
    <script src="./index.js"></script>
  </body>
</html>
// index.js
console.log('hello parcel')

Теперь давайте добавим сценарии разработки и сборки пакетов в package.json:

...
"start": "parcel index.html",
"build": "parcel build index.html --public-url ./"
...

Затем запустите сервер разработки с $ npm start и посетите в браузере localhost: 1234. Вы должны увидеть журнал консоли от index.js! 🎉

Хорошо, теперь часть Hyperapp. Чтобы облегчить жизнь, воспользуемся синтаксисом ES6, а JSX - компилятором babel. К счастью, он уже включен в Parcel, нам просто нужно дать babel подсказку, что нам понадобится пресет env и, что более важно, чтобы скомпилировать JSX для Hyperapp, а не для React. То есть вместо React.createElementfunction мы хотим h function. Создайте следующий файл .babelrc в корне проекта:

{
  "presets": ["env"],
  "plugins": [
    [
      "transform-react-jsx",
      {
        "pragma": "h"
      }
    ]
  ]
}

На этом мы закончили настройку и наконец можем приступить к написанию приложения. Начнем с простого представления Hyperapp:

import { h, app } from 'hyperapp'
const view = () =>
  <div>
    hello hyperapp
  </div>
app({}, {}, view, document.body)

Вы должны сразу увидеть результаты, так как parcel автоматически перезагружает приложение. Приведенный выше код должен быть довольно понятным, за исключением функции app: первые два аргумента - это состояние и действия, которые мы пока не используем, третий, очевидно, функция view, а последний - это элемент DOM, к которому мы хотите визуализировать вид (в реальной жизни не отображать на тело).

По сути, это все, что вам нужно, чтобы начать разработку веб-приложения с помощью Parcel & Hyperapp - довольно просто, правда?

Теперь перейдем к части загрузки пользователя GitHub. Первое, что нам нужно, это какое-то состояние для хранения пользовательского ввода и извлеченных пользовательских данных (Hyperapp не имеет концепции состояния компонента, есть только состояние приложения):

const state = {
  username: '',
  userData: null,
}

И тогда нам понадобится способ изменить это состояние, верно? Заимствованные у Elm и Redux, изменения состояния в Hyperapp - это функции, которые получают состояние (и действия) и возвращают новое состояние, например:

const nameChangeAction = (name) => (state, actions) => ({...state, name})

Вот так будут выглядеть действия в нашем приложении:

const actions = {
  updateUsername: (username) => (state, actions) => {
    getUserData(username).then(actions.setUserData)
    return { username }
  },
  setUserData: userData => state => ({ userData })
}

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

И, конечно, нам нужна эта getUserData функция. Мы нажимаем GitHub API, когда пользователь вводит данные, но, чтобы быть хорошими интернет-гражданами, мы не будем делать это при каждом нажатии клавиши. Давайте возьмем средство защиты от ошибок: $ npm i debounce-promise babel-preset-es2015, импортируем его и создадим функцию getUserData:

const getUserDataFn = username => {
  return fetch(`https://api.github.com/users/${username}`)
    .then(res => res.json())
}
const getUserData = debounce(getUserDataFn, 700)

Добавьте таблицу стилей, импортируйте ее в файл index.js и обновите код view и аргументы функции app:

const view = (state, actions) =>
  <main>
    <div>Search github users:</div>
    <input
      type='text'
      className='searchInput'
      value={state.username}
      oninput={e => actions.updateUsername(e.target.value)}
    />
    <br/>
    <div className='userCard'>
      {state.userData ? (
        <div>
          <img class='userCard__img' src={state.userData.avatar_url} />
          <div class='userCard__name'>{state.userData.name}</div>
          <div class='userCard__location'>{state.userData.location}</div>
        </div>
      ) : (
        <div>👆 search 'em</div>
      )}
    </div>
  </main>
app(state, actions, view, document.body)

Вот и все! При заполнении ввода необходимо сделать запрос и отобразить информацию в представлении.

В заключение

Hyperapp и Parcel - отличные примеры развития программных инструментов. Существует множество идей и шаблонов для создания интерактивного интерфейса - некоторые оказываются более устойчивыми и полезными, в то время как другие очень быстро уходят в прошлое, особенно в области JavaScript. Комбинация React и Redux стала очень популярной среди разработчиков интерфейса, поэтому их ключевые идеи можно увидеть в Hyperapp. Webpack позволил обеспечить большую гибкость в связывании ресурсов, поэтому был разработан ряд требований к пакету ресурсов, который Parcel выполняет и может стать следующим «стандартным» инструментом для работы.

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

Если вам понравился этот пост, нажмите кнопку хлопка ниже 👏👏👏

Вы также можете подписаться на нас в Facebook, Twitter и LinkedIn.