Почему мы выбрали Parcel для нашего фреймворка микрофронтенда Piral

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

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

Самым известным сборщиком, без сомнения, является Webpack. Как проект, он стартовал уже в 2011 году, но потребовалось по крайней мере до 2014 года, когда он действительно нашел общий язык.

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

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

Используйте такие инструменты, как Bit.dev (Github) для совместного использования и синхронизации компонентов пользовательского интерфейса между вашими микрофронтами, сохраняя при этом независимость каждой команды.

Через Bit.dev каждая команда может собирать и организовывать свои компоненты в общую коллекцию, позволяя другим использовать и даже обновлять компоненты из своих собственных проектов, а также поддерживать синхронизацию во всей организации и между проектами.

Попробуйте или узнайте больше здесь.

Выбор правильного инструмента

Компоновщик занимается просмотром дерева (JS) модулей и созданием распределяемого вывода. Это делается в трех фазах:

  1. Коллекция
  2. Трансформация
  3. Оптимизация

В зависимости от сборщика эти три этапа более или менее очевидны. В то время как сбор ресурсов требует знания файлов исходного кода (например, как модули ссылаются на JavaScript, как на ресурсы ссылаются в HTML,…), фаза преобразования требуется для нормализации данной информации.

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

В общем, есть две крайности:

  1. Компоновщики, которые пытаются сделать как можно больше внутри ядра (например, Parcel, FuseBox)
  2. Компоновщики, использующие плагины для заполнения различных этапов живыми (например, Webpack, Rollup)

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

Некоторые сборщики в основном специализируются на работе с JavaScript (например, Browserify, Rollup) и не будут (полностью) работать с общими проектами веб-интерфейса. Здесь требуется работа с CSS или его вариантами, изображениями и другими форматами.

Тем не менее, сборщики также могут использоваться для (чистых) проектов Node.js.

Распространение одного JS, который уже включает все зависимости, может быть весьма полезным.

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

Сейчас существует множество разных сборщиков. Пожалуй, самые популярные из них:

Сообщите нам, если мы пропустили один (например, микробандл). Обновим репозиторий GitHub.

Давайте просто проведем оценку на основе небольшого примера проекта.

Небольшой пример проекта

Рассмотрим следующую ситуацию: у нас есть набор файлов, которые мы хотим объединить и оптимизировать для Интернета.

У нас есть:

  • один HTML-файл, возможно, точка входа в наше веб-приложение
  • один файл SASS, который нужно преобразовать в CSS
  • два файла TypeScript React, которые следует рассматривать как два пакета (один ссылается на другой для сценария разделения пакета)
  • изображение (JPG), на которое ссылается один из файлов TypeScript

В идеале мы ожидаем получить 1 файл HTML, 1 файл CSS, 2 файла JS и 1 файл JPG.

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

Ключевые показатели для этой оценки:

  • Количество пакетов для установки
  • Количество установленных пакетов
  • Сложность конфигурации, если есть
  • Время связать - при первом запуске и последующих запусках
  • Результирующие размеры пакетов
  • Количество необходимых изменений в исходных файлах проекта

Очевидно, поскольку мы уже начинаем с существующего проекта, некоторые «стандарты» уже соблюдаются. Мы используем

  • import() для асинхронного импорта (следует использовать для разделения пакетов)
  • require() для ссылки на общие ресурсы
  • import from для общего импорта JS

В index.html мы ссылаемся на исходные файлы, например, app.tsx вместо имени, используемого позже (что-то вроде app.js).

Оценка

Для оценки мы использовали стандартные инструменты. Например, количество фактически установленных пакетов было просто получено из фактического чтения того, что npm install вернул нам.

Запуск фактического связывания всегда выполнялся через time npm start, где стартовый скрипт указывал на инструментальные средства интерфейса командной строки сборщика или на сценарий Node.js, использующий API сборщика. Мы всегда выполняли три захода. Затем первое измерение было засчитано для начального цикла, второе - для последующих, а последнее - как приблизительное подтверждение второго измерения.

Размеры пакетов были определены с помощью простого ls -l dist оператора.

Точно так же количество изменений было просто подсчитано с diff. Здесь добавление и удаление (то есть модификация) просто считались одним. То же самое и с перемещением файла.

Сложность конфигурации измерялась строками кода в файле конфигурации. Все файлы конфигурации были разработаны с учетом удобства обслуживания. Так что общее мнение должно быть таким же.

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

Это также не первая оценка сборщиков пакетов. На самом деле такие сравнения довольно распространены, и я бы посоветовал вам провести собственное сравнение при запуске нового проекта.

А пока просто некоторые другие сравнения:

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

Полученные результаты

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

Немного проще оказалась Parcel. Здесь все просто заработало из коробки. Никаких дополнительных плагинов, настроек или чего-либо еще не потребовалось. Он просто сделал то, что должен.

Наиболее резким контрастом был потенциально Rollup. Сначала мы выбрали плагин, который, похоже, заключил бы сделку - используя index.html в качестве точки входа. Однако оказалось, что плагин больше не поддерживается и не совместим. Не было проверки совместимости или чего-то еще - просто загадочная ошибка, которая напомнила нам, что что-то не так с конфигурацией.

Накопительный пакет также был самым крайним в отношении необходимости подключаемых модулей для вещей, которые действительно должны работать из коробки. Примером может служить использование CommonJS. Большинство пакетов NPM по-прежнему (и будут в 2020 году) поставляются как модули CommonJS. Rollup требует наличия плагина для работы с этим. Хуже того, нам нужно указать этому плагину, что он должен делать на самом деле. Следовательно, мы должны продублировать импорт из нашей базы кода в конфигурацию Rollup.

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

В результате один плагин, который мы использовали, не соответствовал желаемому результату. В итоге мы получили формат, который нам не нужен.

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

Конфигурация FuseBox также представляет собой его интерфейс командной строки.

Таким образом, с FuseBox мы получаем технологию «создай свой собственный комплект». Экосистема - по многим причинам - не такая зрелая и обширная, как у Webpack, но, по крайней мере, в нашем тесте все работало хорошо.

Старые кандидаты Browserify и Brunch все еще могут быть пригодны для того или иного варианта использования, однако их возраст показал в тесте. Без разделения пакетов или возможности ссылаться на статические ресурсы они все еще могут быть пригодны для использования в проектах Node.js.

Полный пример проекта доступен на GitHub. В предоставленном readme все результаты собраны в одной таблице.

Заключение

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

Лично для меня сравнение подтвердило мое предпочтение Parcel.

Хотя в прошлом году Parcel совершил прорыв, в этом году он определенно стал зрелым. С Parcel 2 не за горами, у нас по-прежнему будет элегантная альтернатива Webpack.

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

Учить больше