Рубрики
Без рубрики

Введение в то, как работают менеджеры пакетов JavaScript

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

Автор оригинала: Shubheksha Jalan.

Эшли Уильямс является одним из лидеров сообщества Node.js. Она твитна о новых менеджерах по пакетам.

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

Это было правильно, когда новый ребенок на блоке менеджера пакета JavaScript – Пряжа – только что прибыл и генерировал много гудок.

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

У меня было так весело исследовать это. Я хотел бы, чтобы я сделал так давно. Поэтому я написал это простое введение в NPM и пряжу, чтобы поделиться тем, что я узнал.

Давайте начнем с некоторых определений:

Что такое пакет?

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

Что такое менеджер по пакетам?

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

Большинство менеджеров по пакетам жонглирует следующие произведения вашего проекта:

Код проекта

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

Манифест файл

Это файл, который отслеживает все ваши зависимости (управляемые пакеты). Он также содержит другие метаданные о вашем проекте. В мире JavaScript этот файл ваш Package.json.

Код зависимости

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

Блокировка файла

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

Это стоит указывать на этот момент, что пряжа использует LOCKFILE, а NPM нет. Мы поговорим о последствиях этого различия в немного.

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

Плоские против вложенных зависимостей

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

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

Чтобы сделать это ясно, скажем, наше приложение зависит от зависимостей A, B и C, а C зависит от A.

Плоские зависимости

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

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

Предположим, что пакет A обновляется до версии 2.0. Если ваше приложение совместимо с версией 2.0, но пакет C не, то нам нужны две версии пакета A, чтобы сделать наше приложение правильно. Это известно Зависимость ада.

Вложенные зависимости

Одно простое решение для решения проблемы зависимости ада состоит в том, чтобы иметь две разные версии пакета A – версии 1.0 и версии 2.0.

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

Диспетчер пакетов должен пройти несколько уровней для разрешения зависимостей.

У нас может быть несколько копий одной зависимости в такой схеме.

Но, как вы могли догадаться, это тоже приводит к нескольким проблемам. Что делать, если мы добавим другой пакет – пакет D – и зависит от версии 1.0 пакета A?

Так что с этой схемой мы можем оказаться Дублирование версии 1.0 пакета A. Это может вызвать путаницу и занимает ненужное дисковое пространство.

Одним из решений к вышеуказанной задаче состоит в том, чтобы иметь две версии пакета A, V1.0 и V2.0, но только одну копию V1.0, чтобы избежать ненужного дублирования. Это Подход, взятый NPM V3 , что уменьшает время, необходимое для прохождения дерева зависимости значительно.

Как Эшли Уильямс объясняет, NPM V2 устанавливает зависимости в гнездовой манере Отказ Вот почему NPM V3 значительно быстрее по сравнению.

Детерминизм против не детерминизм

Другая важная концепция в руководителях пакетов – это детерминизм. В контексте JavaScript Ecosystem детерминизм означает, что все компьютеры с данным Package.json Файл все будет иметь то же самое иное дерево зависимостей, установленных на них в их node_modules папка.

Но с нетерминированным менеджером пакета это не гарантируется. Даже если у вас точно такой же Package.json На двух разных компьютерах, макет вашего node_modules может отличаться между ними.

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

NPM V3, по умолчанию имеет не детерминированные установки и предлагает Функция Shrinkwrap сделать установки детерминированы. Это записывает все пакеты на диске в LockFile вместе с их соответствующими версиями.

Пряжа предлагает детерминированные усталы, поскольку он использует Lockfile для блокировки всех зависимостей рекурсивно на уровне приложения. Таким образом, если пакет A зависит от V1.0 пакета C, и пакет B зависит от V2.0 пакета A, оба из них будут записаны в ложноустройство отдельно.

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

Итак, теперь мы можем вернуться к первоначальному вопросу, который начал меня на этом обучении Spree в первую очередь: Почему она считается хорошей практикой, чтобы иметь LockFiles для приложений, но не для библиотек?

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

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

Если у нас был LockFile для каждой зависимости (библиотеки), которую мы использовали в приложении, и приложение было вынуждено уважать эти локоны, было бы невозможно добраться до ближайшей к плоской структуре зависимости, мы говорили о ранее, с семантическая версия Гибкость, которая является лучшим сценарием дела для разрешения зависимостей.

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

Это не значит, что библиотеки не могут иметь Lockfiles. Они, безусловно, могут. Но основным выносным положением является то, что управляющие пакетами, такие как пряжа и NPM – которые потребляют эти библиотеки – не уважают эти блокировки.

Спасибо за прочтение! Если вы считаете, что этот пост был полезен, пожалуйста, нажмите «︎❤», чтобы помочь продвинуть эту часть другим.