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

Всякий раз, когда один из моих коллег-разработчиков сталкивался с ошибкой плагина Broccoli ... я обычно говорил «rm -rf node_modules», это то, что мне говорили старшие, и я продолжал традицию.

Это очень расстраивало, и, как новичок, я обычно виню во всем Эмбер, так как не понимал многого из того, что происходило. Со временем я понял, что виноват npm. Но несколько месяцев назад я обнаружил менеджер этого пакета Yarn. Когда я его нашел, я прочитал, что он обещает решить наиболее частые ошибки установки npm. Он утверждал, что это было лучше, потому что это было:

· Детерминированный, в отличие от npm.

· Производительность сети при параллельной установке.

· Установка пакета такая же, как и у npm (используется тот же реестр).

· Yarn использует контрольные суммы для проверки целостности пакетов.

· Работает даже в автономном режиме для ранее установленных пакетов, поскольку кэширует все пакеты.

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

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

1. Пакеты

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

2. Зависимости

Они определяют пакеты, которые использует ваше приложение. Они указываются внутри файлов манифеста, например package.json. Следующие зависимости могут быть представлены следующим образом:

«Зависимости»: {
«a»: «1.0.0»,
«b»: «1.0.0»
}

Они используют семантическое управление версиями, т.е.

я. Дан номер версии MAJOR.MINOR.PATCH.

II. ОСНОВНАЯ версия при внесении несовместимых изменений API,

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

iv. Версия PATCH при исправлении ошибок с обратной совместимостью.

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

Итак, давайте начнем с примера установки npm, а затем продолжим установку пряжи. Я сделаю пример простым, но очень подробным.

Предположения

я. Это будет наша первая установка package.json.

II. На данный момент нет папки node_modules.

iii. Нет предварительно кэшированных пакетов.

Установка пакета состоит из трех этапов.

я. Разрешение зависимости

Делайте запросы в реестр и рекурсивно ищите зависимости и определяйте место установки пакета в папке зависимостей.

ii. Получать пакеты

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

iii. Связывание пакетов

Копирование файлов из глобального кеша в локальную папку node_modules.

Тем не менее, давайте посмотрим, как на самом деле происходит вышеуказанное, когда мы выполняем «npm install».

Теперь рассмотрим файл манифеста (package.json), содержащий следующие простые гипотетические пакеты.

«Зависимости»: {
«a»: «1.0.0»,
«b»: «1.0.0»
}

Мы сделаем его более простым, удалив второстепенные версии и версии с исправлениями и оставив только основные версии. Это оставляет нам следующее:

Когда мы выполняем «npm install» для указанного выше файла package.json, npm выполняет следующие действия:

1. Загрузочные пакеты:

а. Если папка node_modules уже присутствует (т.е. вы ранее использовали «npm install», которая, в свою очередь, создает папку npm_modules), то использует ее для создания идеального дерева путем загрузки с диска.

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

c. Используя клонированное дерево, создайте идеальное дерево, которое будет использоваться для создания папок пакетов в папке node_modules. Это можно увидеть на снимке ниже.

Сначала мы сталкиваемся с пакетом «a1», у которого есть еще одна зависимость от «s1», так как мы впервые видели его, поэтому мы следуем плоской структуре и помещаем ее как общую зависимость для «a1» и «b1». Эта структура позволяет нам повторно использовать этот пакет для другого пакета, который может зависеть от «s1».

Теперь, когда мы сталкиваемся с «s2», который является версией 2 того же пакета «s», мы не можем следовать плоской структуре, поскольку одни и те же пакеты не могут находиться в одном каталоге. Таким образом, мы рассматриваем его как дочерний элемент для «b1», а папка для «s2» создается внутри «b1».

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

2. Разрешение зависимости:

а. На основе идеального дерева npm определяет, какие пакеты необходимо установить, а какие уже установлены. Для нашего случая так же не существует идеала, так как мы начали установку с нуля.

б. Он также разрешает версии, используемые во вложенных пакетах и ​​в плоском пути к каталогу.

c. На этом этапе npm знает, какие пакеты в какие папки нужно установить.

3. Получение пакетов и связывание

а. Здесь npm фактически извлекает пакеты из реестра npm и устанавливает их в соответствующие папки для пакетов.

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

1. Разрешение зависимости:

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

б. Теперь, когда у нас есть имя пакета и его номер версии, Yarn переходит в репозиторий npm (реестр) и находит ту же или более новую версию пакета, как указано в файле манифеста. Мы можем упомянуть пакет, который необходимо получить, в package.json или файле манифеста. Следующие символы используются для обозначения того, какую версию необходимо загрузить.

я. ‘~’: Исправляет как основной, так и дополнительный номер версии, при этом совпадая с любым номером патча. Бывший. ~ 2.1.0 означает, что получить что-либо выше 2.1.0, но ниже 2.2.0.

II. ‘^’: Он блокирует основную версию и ищет последнюю версию для дополнительных версий и версий исправлений. Ex ^ 2.1.0 означает выборку выше 2.1.0 и ниже 3.0.0

iii. ‘*’: Он блокирует ОСНОВНОЙ или НЕЗАВИСИМЫЙ в зависимости от того, где он используется. Пример 2. * означает все, что ниже версии 3.0.0 и 2.0. * Означает все, что меньше 2.1.0

c. Теперь Yarn проверяет локальный кеш перед тем, как сделать фактический запрос в реестр. Если пакет, который необходимо установить, уже используется каким-то другим пакетом, тогда нет необходимости запрашивать его снова, поскольку он уже был кэширован yarn для последующего повторного использования.

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

2. Получение и связывание

а. Теперь запрос пакета сделан и получен из реестра. Таким же образом Yarn получает другие пакеты.

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

3. Сохраните файл блокировки.

а. Он используется для хранения точно установленных версий каждой зависимости. Он похож на npm-shrinkwrap.json из npm, но без потерь и дает воспроизводимые результаты. В Rails у вас есть сборщик для подобных вещей. Он управляется Yarn и обновляется каждый раз, когда вы добавляете / удаляете / обновляете существующие пакеты.

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

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

Теперь, когда мы знаем, как работает Yarn, я хотел бы продемонстрировать один из основных недостатков npm и показать вам, как yarn его решает.

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

Теперь предположим, что Иегуда устанавливает пакет следующим образом, используя npm

Предположим, он решает обновить Пакет «a» до «a2». При запуске «npm install» создается следующая структура.

Теперь предположим, что Иегуда хочет поделиться своим кодом со всем миром, и люди начинают использовать «npm install» для вышеуказанного пакета.

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

Это можно решить, очистив папку «node_modules», но это не самый лучший способ сделать это. На самом деле повторная переустановка пакетов займет много времени.

Термоусадочная пленка в помощь… .. но где мне ее найти ???

Он уже там с npm, но по умолчанию отключен и работает с потерями. Так что даже ребята из npm не верят вам.

Теперь Иегуда обнаруживает Ярна и решает попробовать.

Также есть файл блокировки, который поддерживает эту иерархию зависимостей, даже когда вы запускаете «yarn install». Результат одинаков на каждой машине.

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

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

Мы знаем, что Яхуда действительно умен, поэтому он решает усилить интеграцию между Ember и Yarn.

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

Хакерский полдень - это то, с чего хакеры начинают свои дни. Мы часть семьи @AMI. Сейчас мы принимаем заявки и рады обсуждать рекламные и спонсорские возможности.

Если вам понравился этот рассказ, мы рекомендуем прочитать наши Последние технические истории и Современные технические истории. До следующего раза не воспринимайте реалии мира как должное!