Мы задокументировали наш путь к блестящему новому стеку.

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

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

Посещение СПА

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

Однако одним большим недостатком SPA является то, что они обычно зависят от загрузки огромного фрагмента JavaScript, его анализа и выполнения некоторых вызовов API, прежде чем даже можно будет что-либо отобразить на странице.

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

Изоморфный JavaScript

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

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

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

Эффективно связанный код с модулями ES2015

Как только сервер выполнил свою работу, клиент берет на себя ответственность. Для этого он должен загрузить некоторые ресурсы (CSS и JavaScript) и проанализировать их. Эти ресурсы должны быть оптимизированы, чтобы у пользователя был минимально возможный пакет для загрузки, а браузер мог эффективно анализировать код.

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

Мы оценили следующие инструменты: Browserify, Rollup и Webpack. Мы начали с Webpack, так как это был инструмент, с которым мы были знакомы и с которым удобно, и мы могли быстро запустить первую версию. Однако на раннем этапе мы столкнулись с несколькими препятствиями, которые побудили нас дать шанс другим инструментам:

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

Модули CommonJS не поддаются статическому анализу, что означает, что даже если вы используете только часть функциональности в модуле, весь модуль включается в окончательный комплект.

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

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

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

Однако проблема с накоплением пакетов заключается в том, что сообщество довольно мало и не поддерживает такие вещи, как разделение кода или совместное использование памяти при создании нескольких пакетов.

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

Кроме того, был выпущен Webpack 3 с поддержкой подъема области видимости, который представляет собой тот же механизм, который Rollup использует для помещения кода в закрытие одной функции, и будет иметь большое значение для уменьшения размера пакета и времени анализа.

ES2015 с Babel

ECMAScript быстро развивался за последние несколько лет, и многие новые функции внедряются в браузеры с непревзойденной скоростью.

Мы пишем весь наш код в синтаксисе ES2015, потому что мы хотим использовать синтаксис, который в конечном итоге будет изначально понят для браузеров. Это означает, что мы можем просто посмотреть, как используется наш сайт в браузере, и настроить babel-preset-env плагин, чтобы определить, какие функции должны быть перенесены.

Мы также вкратце рассмотрели TypeScript; хотя это, безусловно, интересно, мы еще недостаточно знакомы с ним, чтобы использовать его в производственных целях.

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

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

Принести

Поскольку мы создаем SPA, нам также нужен был способ получить данные в нашем приложении. В идеале мы хотели бы быть «как можно ближе к металлу», просто имея тонкую оболочку вокруг библиотек узлов и браузерных технологий, которая абстрагирует эти различия для нас.

Мы остановились на Fetch, потому что это технология браузера, которая имеет отличную поддержку (Chrome 42+, Firefox 39+, Edge 14+), а также существует пакет на npm, который реализует синтаксис вокруг собственного http-пакета узла.

Для браузеров, у которых нет доступа к Fetch API, существует отличный полифил.

Реагировать

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

В наши дни есть много библиотек на выбор: React, Angular, VueJS… Этот список можно продолжить. Бесконечно. Навсегда. Новые фреймворки создаются каждый день, и кажется, что это никогда не прекратится, поэтому при выборе одного из них было важно быть прагматичным.

Мы были знакомы с двумя библиотеками, которые достигли наибольшего прогресса в сообществе JavaScript, поэтому основными соперниками для нас были React и Angular 2. У нас был положительный опыт работы с обеими библиотеками, и мы были уверены, что можем начать быстро создавать что-то с любой из них.

У обеих этих библиотек есть свои плюсы и минусы, поэтому мы оценили обе. В конце концов, мы выбрали React по нескольким причинам:

  • Angular 2 только недавно вышел из бета-версии, с его помощью не удалось добиться высокого качества продукции.
  • Google, похоже, не особо старается пробовать Angular своими собственными проектами, хотя есть много проектов, которые кажутся идеальными для этого.
  • Facebook создал React, потому что он решил для них проблему, они встроили в него части Facebook, а также весь веб-сайт Instagram - они фактически используют его.
  • Многие другие компании используют React. Это не означает, что мы хотим прибегать к какой-либо подножке, но это действительно означает, что, если что-то случится с Facebook, найдутся другие компании, которые восполнят этот пробел.
  • React - это просто слой представления, вы можете решить, какие еще части вам действительно нужны, и вы можете использовать любую имеющуюся библиотеку.
  • Angular предоставляет все из коробки. Это палка о двух концах, поскольку она помогает быстро приступить к работе, но потенциально есть много вещей, которые вы не используете, что добавляет раздувания.
  • React имеет крошечную область API-интерфейса, что упрощает доступ новых людей, поскольку большую часть времени вы пишете обычный JavaScript, а не какую-то конкретную библиотеку DSL.

Тем не менее, у React есть и недостатки:

  • Лицензия, поставляемая с React, вызвала некоторые проблемы, но с тех пор Facebook создал FAQ, чтобы помочь понять это. В результате несколько компаний, которые ранее запрещали использование React, теперь принимают его.
  • Экосистема React может быть огромной. Есть так много пакетов на выбор, и многие из них, похоже, решают одну и ту же проблему. Важно найти то, что вам удобно, и оставаться прагматичным, прежде чем переходить на новый пакет каждую неделю.

Тем не менее, это не было нарушением правил, поэтому мы решили использовать React.

Redux

Поскольку React - это просто слой представления, нам нужно было найти другую библиотеку, которая помогла бы нам с «модельной» частью приложения. Когда был выпущен React, он популяризировал (по крайней мере, в сообществе JavaScript) концепцию однонаправленного потока данных.

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

Существует довольно много вариантов архитектуры Flux, но ни один из них не попал в цель, пока не появился Redux. Он повысил ставку, фактически не создавая потока вообще, но взяв реплики из языка вяза и улучшив шаблон Flux, который был выложен Facebook.

Redux помогает нам поддерживать состояние всего нашего приложения, сохраняя все, от данных API до информации о том, какой сайт просматривает пользователь.

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

Дополнительные библиотеки

Есть и другие библиотеки, которые мы используем, но мы не будем углубляться в них, поскольку они существенно не влияют на то, как мы структурируем наш код.

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

Управление пакетами и качество кода

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

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

Для модульного тестирования мы используем ava - этот инструмент великолепен, потому что он запускает тесты параллельно, что действительно сокращает время, когда мы пытаемся достичь> 80% охвата модульным тестом.

Мы используем Yarn для управления нашими зависимостями. Это дает нам более быстрые, воспроизводимые сборки, что особенно помогает в нашем процессе CI - сборки теперь занимают секунды, а не минуты, которые они бы заняли при использовании npm 3.

Гид по стилю жизни

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

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

В заключение

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

Мы приветствуем ваши отзывы и предложения - не стесняйтесь разрывать нас в комментариях.

Этот пост является последним в серии статей нашей команды, посвященных:

→ Понравилась эта история? Подпишитесь на Poki, чтобы быть в курсе будущих публикаций!

Дайте нам знать, что вы думаете, нажав 👏 ниже или оставив комментарий.