18

I read this: How do I override nested NPM dependency versions?

Unfortunately, it does not solve my problem.

I am trying to change a package from using a specific dependency to use another version of that dependency.

Is it built into a package what version of a dependency it should use, or is it possible to change it?

In my case specifically, I am trying to change css-loader's default dependency on cssnano@3.10.0 (latest) to instead be dependent on cssnano@4.0.0-rc.2 (next).

From the second answer in the above link, user trickpatty notes that:

this will be removed anytime you run npm i instead of editing your package-lock.json and adding the child dependency to "dependencies" there, add the child dependency to your package.json "dependencies" section

Including cssnano@4.0.0-rc.2 in package.json's devDependencies does nothing to css-loader. It still uses the other (default) version of cssnano.

Magnus
  • 6,791
  • 8
  • 53
  • 84
  • 1
    _"Is it built into a package what version of a dependency it should use"_ <- yes. _"is it possible to change it"_ <- also yes – Phil May 30 '18 at 01:02
  • What makes you think it's not working? Works for me if I run `npm i --save css-loader && npm i --save-dev cssnano@4.0.0-rc.2`. Run `tail node_modules/cssnano/package.json` to confirm. Mine has `"version": "4.0.0-rc.2"` – Phil May 30 '18 at 01:08
  • Thanks @Phil , I think they updated the packages. This was a problem when css-loader used a broken version of cssnano. Thus inspiring me to find out if I could somehow force it to use another version. – Magnus May 30 '18 at 01:12
  • The version of `cssnano` that `css-loader@0.28.11` depends on is still `3.10.0`. I'll ask again; what makes you think it's not working? – Phil May 30 '18 at 01:14
  • 1
    @Phil If you run `npm list cssnano` you will see that there are two versions of cssnano installed, but that css-loader indeed still is dependent on the lower version (it shows as a "subfolder") – Magnus May 30 '18 at 01:33
  • `npm list` shows the dependencies of the package but they won't necessarily won't be what's installed. Given NPM's flat directory structure, you can only have one copy of a library installed. – Phil May 30 '18 at 02:13
  • @Phil Ah, ok, so we can be absolutely certain that even though `npm list` shows a structure like that, it actually uses the version that's installed? I wonder how the developers would protect against this. I mean, do they just openly allow their module to use any version of a dependency (whichever is installed), or is it just versions "higher than X" or similar... – Magnus May 30 '18 at 12:52
  • 1
    @Phil "Given NPM's flat directory structure" - um, NPM famously has a highly nested directory structure, with multiple versions of every package able to be installed. Are you thinking of something else? – OrangeDog Dec 03 '19 at 12:56
  • 1
    @Magnus Phil is completely wrong. Each package uses its nested dependencies first – OrangeDog Dec 03 '19 at 12:57
  • @Phil I used it in 2018 and 2017 and 2011. The module system has always worked like that. – OrangeDog Dec 03 '19 at 20:26
  • 1
    @StopHarmingMonica I'm just going by what I thought I saw at the time. I could have sworn everything was at the top level of `node_modules`. I'm also quite happy to be wrong here. Glad I didn't provide an answer then :). _Edit:_ pretty sure this is what I was seeing ~ https://npm.github.io/how-npm-works-docs/npm3/how-npm3-works.html, obviously I got confused – Phil Dec 03 '19 at 23:45

5 Answers5

2

NPM 8 introduced "overrides" which allows you to override specific transitive dependencies of your direct dependency. For your usecase, you would declare something like below in your package.json.

{
  "overrides": {
    "css-loader": {
      "cssnano": "4.0.0-rc.2"
    }
  }
}

More details @ https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides

Sateesh
  • 735
  • 8
  • 10
2

There are several alternatives:

  • If you can use different package manager, yarn has an option to achieve it by adding to the package.json:
"resolutions": {
    "package-a": "2.0.0"
}

EDIT: Found another alternative: https://www.npmjs.com/package/npm-force-resolutions

JHH
  • 63
  • 7
1

The following in your package.json can help you here. How it works is that it overrides all the versions of cssnano that css-loader requests with the version you've specified instead.

See the docs

"overrides": {
  "css-loader": {
     "cssnano": "1.2.3"
   }
}
Slbox
  • 10,957
  • 15
  • 54
  • 106
-2

In package.json you can add resolutions and give the path of dependency which was used. This is example from my project:

{
  "resolutions": {
    "helmet/helmet-csp": "2.9.1",
    "jest/**/handlebars": "4.5.3"
  }
}
Eduard
  • 1,768
  • 2
  • 10
  • 14
  • 1
    This is a feature of yarn, not npm – Maddis Jan 21 '21 at 16:55
  • If you want to use `resolutions` in NPM, you need to use it in conjunction with _npm-force-resolutions_ (https://github.com/rogeriochaves/npm-force-resolutions). This is useful for supporting users below npm 8.3, which is when `overrides` was introduced into NPM itself. However, it should be noted the nested/wildcard notation will +NOT+ work with _npm-force-resolutions_ but only with `yarn`, as the first comment here correctly states. – runderworld Jan 25 '23 at 18:43
-4

This thread is a bit old and maybe already resolved, but maybe there is someone with the same question.

In my opinion, you should not change the dependency versions of your dependencies. Each project is developed, tested, and published considering their declared dependency versions. You could break or change the behavior of a package changing its dependencies externally.

Instead, think in making a fork of the project (css-loader), change the dependency version, test by yourself, and do use your fork. You can also open a pull request to the project maintainer (if you think the change will benefit the community) or publish your version (respecting the licensing policy).

Paulo Candido
  • 167
  • 2
  • 9
  • 3
    This is done for security purposes mostly or else the entire application will in be in jeopardy we don't change just because we love to :) – Robert Ellis Jan 21 '22 at 11:29