Как переопределить вложенные версии зависимостей 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 ?

Некоторый дополнительный контекст:

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 с другим пакетом . Для получения подробной информации о том, почему вы когда-либо захотите это сделать, обратитесь к следующему вопросу:

Как полностью переопределить вложенную подзависимость 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 не сработало для меня, поэтому я сделал, чтобы переопределить версию вложенной зависимости:

  1. Удалите вложенную зависимость в разделе "требует" файла package-lock.json.
  2. Добавьте обновленную зависимость в DevDependencies в package.json, чтобы модули, которым она требуется, по-прежнему могли получить к ней доступ.
  3. нпм я

Я собирался спуститься npm-force-resolutions route, но кажется, что простое включение зависимости в мою собственную проблему устранило для меня проблему.

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

Пример

Проблема

Мне нужно обновить до версии 3.6.9 из 3.6.8

Моя

      {
  "dependencies": {
    "react-plyr": "^3.2.0"
  }
}

React Plyr

      {
  "dependencies": {
    "plyr": "^3.6.8"
  }
}

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

https://docs.npmjs.com/about-semantic-versioning#using-semantic-versioning-to-specify-update-types-your-package-can-accept

Обновление шахты

Это обновляет 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.

  1. Создайте новый временный проект с npm init
  2. Установить пакет A npm i A@version --save
  3. Установить пакет B npm i B@fixed_version --save
  4. Открой package-lock.json файл и скопировать всю корневую зависимость пакета B.
  5. Удалить пакет B npm un B --save
  6. Удалить node_modules папка и package-lock.json
  7. Установите все остальные зависимости npm i
  8. Открой package-lock.json файл и вставьте зависимость корневого уровня, которую вы скопировали ранее.
  9. Настройте версию пакета B в зависимостях пакета A на фиксированную версию.
  10. Удалить node_modules папка.
  11. Установить без побочных эффектов 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" снова изменяется, как и до вашего изменения.

Другие вопросы по тегам