Как переопределить вложенные версии зависимостей NPM?
Я хотел бы использовать grunt-contrib-jasmine
Пакет NPM. Это имеет различные зависимости. Часть графа зависимостей выглядит так:
─┬ grunt-contrib-jasmine@0.4.1
│ ├─┬ grunt-lib-phantomjs@0.2.0
│ │ ├─┬ phantomjs@1.8.2-2
К сожалению, в этой версии есть ошибка phantomjs
что препятствует правильной установке в Mac OS X. Это исправлено в последней версии.
Как я могу получить grunt-lib-phantomjs
использовать более новую версию phantomjs
?
Некоторый дополнительный контекст:
grunt-contrib-jasmine
явно требует версию"~0.2.0"
изgrunt-lib-phantomjs
, которая явно требует версии"~1.8.1"
изphantomjs
,- Добавление
phantomjs
на зависимости моего пакета сначала ничего не влияет; обе версии установлены иgrunt-contrib-jasmine
все еще использует более старые версии (см.: При установке пакета с NPM, можете ли вы сказать ему использовать другую версию одной из его зависимостей?).
15 ответов
Вы, наверное, уже нашли обходной путь для этого.
В любом случае, вы можете использовать функциональность npm shrinkwrap, чтобы переопределить любую зависимость или суб-зависимость.
Я только что сделал это в нашем грандиозном проекте. Нам нужна была более новая версия connect, начиная с 2.7.3. доставляла нам неприятности. Поэтому я создал файл с именем npm-shrinkwrap.json:
{
"dependencies": {
"grunt-contrib-connect": {
"version": "0.3.0",
"from": "grunt-contrib-connect@0.3.0",
"dependencies": {
"connect": {
"version": "2.8.1",
"from": "connect@~2.7.3"
}
}
}
}
}
npm должен автоматически поднять его во время установки для проекта.
(См.: https://nodejs.org/en/blog/npm/managing-node-js-dependencies-with-shrinkwrap/)
Для тех, кто с 2018 года и позже, используя npm версии 5 или новее: отредактируйте package-lock.json
: удалить библиотеку из "requires"
раздел и добавить его под "зависимости".
Например, вы хотите deglob
пакет для использования glob
версия пакета 3.2.11
вместо его текущего. Вы открываете package-lock.json
и посмотреть:
"deglob": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.0.tgz",
"integrity": "sha1-TUSr4W7zLHebSXK9FBqAMlApoUo=",
"requires": {
"find-root": "1.1.0",
"glob": "7.1.2",
"ignore": "3.3.5",
"pkg-config": "1.1.1",
"run-parallel": "1.1.6",
"uniq": "1.0.1"
}
},
Удалить "glob": "7.1.2",
от "requires"
, добавлять "dependencies"
с правильной версией:
"deglob": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.0.tgz",
"integrity": "sha1-TUSr4W7zLHebSXK9FBqAMlApoUo=",
"requires": {
"find-root": "1.1.0",
"ignore": "3.3.5",
"pkg-config": "1.1.1",
"run-parallel": "1.1.6",
"uniq": "1.0.1"
},
"dependencies": {
"glob": {
"version": "3.2.11"
}
}
},
Теперь удалите свой node_modules
папка, запустить npm install
и это добавит недостающие части к "dependencies"
раздел.
Начиная с NPM v8.3, правильный способ справиться с этим — через
Если вам нужно внести определенные изменения в зависимости ваших зависимостей, например, заменить версию зависимости известной проблемой безопасности, заменить существующую зависимость ответвлением или убедиться, что везде используется одна и та же версия пакета, то вы можете добавить переопределение.
Переопределения позволяют заменить пакет в дереве зависимостей другой версией или полностью другим пакетом. Эти изменения могут быть как конкретными, так и расплывчатыми по желанию.
Чтобы убедиться, что пакет foo всегда установлен как версия 1.0.0, независимо от того, на какую версию полагаются ваши зависимости:
{ "overrides": { "foo": "1.0.0" } }
Существует множество других, более тонких конфигураций, позволяющих переопределять пакет только в том случае, если он зависит от конкретной иерархии пакетов. Дополнительные сведения см. на странице https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides.
Единственное решение, которое сработало для меня (node 12.x, npm 6.x), было использование npm-force-resolution, разработанного Rogerio Chaves.
Сначала установите его:
npm install npm-force-resolutions
Можете добавить --ignore-scripts
если какие-то неработающие скрипты транзитивных зависимостей блокируют установку чего-либо.
Затем в package.json
определите, какая зависимость должна быть переопределена (вы должны установить точный номер версии):
"resolutions": {
"your-dependency-name": "1.23.4"
}
И в "scripts"
раздел добавить новую предустановочную запись:
"preinstall": "npx npm-force-resolutions",
Сейчас же, npm install
применит изменения и силу your-dependency-name
быть в версии 1.23.4
для всех зависимостей.
Для тех, кто использует пряжу.
Я пытался использовать npm shrinkwrap, пока не обнаружил, что пряжа cli проигнорировала мой файл npm-shrinkwrap.json.
Пряжа имеет https://yarnpkg.com/lang/en/docs/selective-version-resolutions/ для этого. Ухоженная.
Проверьте этот ответ тоже: /questions/1399833/kak-pereopredelit-vlozhennyie-zavisimosti-s-pomoschyu-yarn/1399850#1399850
Основываясь на остальных ответах, я предлагаю то же решение, но я показываю package.json, так как я немного боролся с тем, где разместить переопределение и как.
{
"name": "my-app",
"version": "snapshot",
"scripts": {
"ng": "ng",
"build-dev": "ng build --configuration development",
},
"private": true,
"dependencies": {
"@angular/animations": "~14.2.9",
"@angular/common": "~14.2.9"
...
},
"devDependencies": {
"@angular-devkit/build-angular": "^14.2.8",
....
},
"overrides": {
"loader-utils@>2.0.0 <3": "2.0.4",
"loader-utils@>3.0.0 <4": "3.2.1"
}
}
В связи с уязвимостью безопасности «loader-utils» от ноября 2022 г. было запрошено
- используйте версию 2.0.4, если вы находитесь в 2.X
- используйте версию 3.2.1, если вы находитесь в 3.X
И чтобы проверить
- добавьте package.json тег переопределения
- удалить package-lock.json
- запустите «установить npm»
- запустить «аудит npm»
Вложенная замена совершенно другим пакетом
Большинство стратегий, описанных в других ответах здесь, хорошо работают, если вы просто заинтересованы в переопределении номера версии пакета, но в нашем случае нам нужно было найти способ переопределить вложенную подзависимость npm с другим пакетом . Для получения подробной информации о том, почему вы когда-либо захотите это сделать, обратитесь к следующему вопросу:
Укажите tarball напрямую
Для вложенной замены пакета совершенно другим пакетом с использованием стратегии, упомянутой другими, вам просто нужно предоставить ссылку на архив, где вы обычно указываете номер версии переопределения.
Например, для случая замены уязвимого пакета,
ansi-html
, с фиксированной вилкой этого пакета,
ansi-html-community
, раздел разрешений должен выглядеть следующим образом:
"resolutions": {
"ansi-html": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz"
}
Чтобы найти ссылку на архив, используйте следующую команду, при необходимости изменив реестр:
npm view ansi-html-community dist.tarball --registry=https://registry.npmjs.org/
Также обратите внимание, что для
npm-force-resolutions
работать, когда вы бежите
npm install
, вам понадобится
preinstall
вход под
scripts
часть
package.json
:
"scripts": {
"preinstall": "npx npm-force-resolutions"
}
Ответ @user11153 работал у меня локально, но при попытке выполнить чистую установку (также как удаление
node_modules
), Я бы получил:
npm-force-resolutions: command not found
Мне пришлось обновить
preinstall
сценарий должен быть:
"preinstall": "npm i npm-force-resolutions && npm-force-resolutions"
Что гарантирует, что
npm-force-resolutions
пакет устанавливается перед попыткой его запуска.
При этом, если вы можете использовать пряжу вместо этого, я бы сделал это, а затем использовал ответ @Gus.
У меня возникла проблема, когда одна из вложенных зависимостей имела уязвимость аудита npm, но я все же хотел сохранить версию родительской зависимости. решение npm shrinkwrap не сработало для меня, поэтому я сделал, чтобы переопределить версию вложенной зависимости:
- Удалите вложенную зависимость в разделе "требует" файла package-lock.json.
- Добавьте обновленную зависимость в DevDependencies в package.json, чтобы модули, которым она требуется, по-прежнему могли получить к ней доступ.
- нпм я
Я собирался спуститься
npm-force-resolutions
route, но кажется, что простое включение зависимости в мою собственную проблему устранило для меня проблему.
Я считаю, что в моем случае это сработало, потому что исходная зависимость допускает патч-версии рассматриваемой зависимости, которые я хотел обновить. Таким образом, вручную добавляя новую версию, он по-прежнему выполняет зависимость исходной зависимости и будет использовать ту, которую я добавил вручную.
Пример
Проблема
Мне нужно обновить до версии
3.6.9
из
3.6.8
Моя
{
"dependencies": {
"react-plyr": "^3.2.0"
}
}
React Plyr
{
"dependencies": {
"plyr": "^3.6.8"
}
}
Уведомление о зависимости, с которой он начинается
^
это означает, что он может принимать любые незначительные исправления. Вы можете узнать об этом больше здесь:
Обновление шахты
Это обновляет
plyr
зависимость от моего.
package.json
{
"dependencies": {
"plyr": "^3.6.9",
"react-plyr": "^3.2.0"
}
}
Вы также можете рассмотреть следующий подход.
Предположим, что ваш проект зависит от пакета A, который, в свою очередь, зависит от пакета B. Создание этой цепочки зависимостей: your_project -> Package A -> Package B
, В версии пакета B существует ошибка, от которой зависит пакет A, и вы хотите обновить версию сейчас, а не через месяц.
Примените эти шаги
Для начала начните с шага 1. Для работы в вашем собственном проекте начните с шага 3.
- Создайте новый временный проект с
npm init
- Установить пакет A
npm i A@version --save
- Установить пакет B
npm i B@fixed_version --save
- Открой
package-lock.json
файл и скопировать всю корневую зависимость пакета B. - Удалить пакет B
npm un B --save
- Удалить
node_modules
папка иpackage-lock.json
- Установите все остальные зависимости
npm i
- Открой
package-lock.json
файл и вставьте зависимость корневого уровня, которую вы скопировали ранее. - Настройте версию пакета B в зависимостях пакета A на фиксированную версию.
- Удалить
node_modules
папка. - Установить без побочных эффектов
npm i --no-save
Теперь вы должны увидеть корневую зависимость в вашем проекте node_modules
папка с фиксированной версией.
Примечание: я не проверял это для ситуаций, когда есть несколько зависимостей корневого уровня, которые зависят от пакета B. Итак, your_project -> Package A -> Package B
а также your_project -> Package C -> Package B
, Я подозреваю, что это все еще будет работать, и Package C будет поддерживать свою собственную версию, но я не уверен.
Почему это так?
Используя эти шаги, вы позволяете npm выполнять большую часть работы за вас. Например, он также генерирует хэш целостности для пакета B.
Почему шаг X?
Шаг 3: Это добавляет фиксированную версию пакета B в качестве зависимости первой степени и корректирует текущую package-lock.json
, Тем не менее, пакет A по-прежнему зависит от сломанной версии пакета B. который он поддерживает в своем собственном node_modules
папка.
Шаг 5: То же, что и шаг 3, за исключением полного удаления пакета B.
Шаг 6: Это должно произойти, потому что мы хотим, чтобы пакет B был зависимостью корневого уровня при новой установке.
Шаг 7: При этом устанавливаются все зависимости, возвращается к "сломанной" ситуации и создается package-lock.json
файл с испорченной версией пакета B на корневом уровне.
Шаг 10 + 11: Это гарантирует, что мы имитируем новую установку. NPM всегда ищет package-lock.json
файл, если нет папки 'node_modules'. С помощью --no-save
обеспечивает отсутствие побочных эффектов, таких как изменения package-lock.json
файл.
Простейшим минимумом является добавление только начальной сжатой зависимости json в package.json. Необходимы "от" и "до"
"grunt-contrib-connect": {
"version": "0.3.0",
"from": "grunt-contrib-connect@0.3.0",
"dependencies": {
"connect": {
"version": "2.8.1",
"from": "connect@~2.7.3"
}
}
}
NPM термоусадочная пленка предлагает хорошее решение этой проблемы. Это позволяет нам переопределить эту версию конкретной зависимости конкретного субмодуля.
По сути, когда вы запускаете npm install, npm сначала просматривает ваш корневой каталог, чтобы узнать, существует ли файл npm-shrinkwrap.json. Если это произойдет, он будет использовать это сначала для определения зависимостей пакетов, а затем перейдет к обычному процессу работы с файлами package.json.
Чтобы создать npm-shrinkwrap.json, все, что вам нужно сделать, это
npm shrinkwrap --dev
код:
{
"dependencies": {
"grunt-contrib-connect": {
"version": "0.3.0",
"from": "grunt-contrib-connect@0.3.0",
"dependencies": {
"connect": {
"version": "2.8.1",
"from": "connect@~2.7.3"
}
}
}
}
}
Сначала запустите это
npm i -D @types/eslint@8.4.3
это решит проблему
Я нашел решение, которое мне помогло.
Так. Сначала отредактируйте файл npm-shrinkwrap.json, как рекомендуют все остальные решения.
Затем (в Windows):
- Щелкните правой кнопкой мыши файл npm-shrinkwrap.json.
- Свойства
- В разделе "Атрибуты" выберите "Только для чтения". Это предотвратит изменение npm файла mpn-shrinkwrap.json.
Другие предлагаемые решения достаточно хороши, если вы выполняете операцию "npm install" только один раз. Но после первой "npm install" файл "npm-shrinkwrap.json" снова изменяется, как и до вашего изменения.