510

Is there a way to simply uninstall all unused (undeclared) dependencies from a Node.js project (ones that are no longer defined in my package.json.) When I update my application I like to have the unreferenced packages removed automatically.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Tarion
  • 16,283
  • 13
  • 71
  • 107
  • 1
    Unused by what? Do you mean to remove folders from `node_modules` when they're removed from the respective `package.json`? – SLaks Jan 28 '14 at 21:19
  • 1
    exactly, mhm npm ll already gives a good hint which are the candidates. – Tarion Jan 28 '14 at 21:20

4 Answers4

787

Note: Recent npm versions do this automatically when running npm install if package-locks are enabled, so this is not necessary except for removing development packages with the --production flag.


Run npm prune to remove modules not listed in package.json.

From npm help prune:

This command removes "extraneous" packages. If a package name is provided, then only packages matching one of the supplied names are removed.

Extraneous packages are packages that are not listed on the parent package's dependencies list.

If the --production flag is specified, this command will remove the packages specified in your devDependencies.

Darkhogg
  • 13,707
  • 4
  • 22
  • 24
  • 5
    If I read that correctly, this would remove all sub-dependencies, since they're not listed in `package.json`. Is that right? So, the next update or install would have to reinstall them. – nshew13 Apr 18 '14 at 14:14
  • 1
    Yes, it will remove sub-dependencies. Sub-dependencies are actually stored inside the module's own `node_modules` directory, so they are removed with the module. – Darkhogg Apr 18 '14 at 14:19
  • 2
    Let me give an example. I remove karma from my `package.json`, but leave bower. When I run `npm prune`, I expect all of karma, including its own `node_modules` folder containing its dependencies, to be removed. What about bower's dependencies (bower-json, bower-logger, chmodr, fstream, glob, et al.). Technically, those aren't listed in my project's `package.json`. Are those removed or not? – nshew13 Apr 18 '14 at 14:27
  • 4
    No, they are not. Note that they're *not* in your own `node_modules`, but *inside* `node_modules/bower/node_modules`, "protected" by `node_modules/bower/package.json`. Dependencies of your package and that of your package's dependencies *are not mixed*. – Darkhogg Apr 18 '14 at 14:30
  • 1
    That was my assumption, but the documentation translates to "This command removes packages that are not listed on the parent package's dependencies list." It would seem to be incorrect, or misleading at best. – nshew13 Apr 18 '14 at 14:41
  • The documentation just does not takes into account sub-dependencies, as they are treated as part of their parent packages. I'll add a clarification to the answer later. – Darkhogg Apr 18 '14 at 15:40
  • If you see an npm module remain in your `node_modules/` folder after running `npm prune` even though it's not in `package.json` - make sure to check your `npm-shrinkwrap.json`. If it's there, the only soluiton is to `rm -rf node_modules` and `npm install` ! – Andy Ray May 04 '15 at 22:25
  • 2
    **and** delete your shrinkwrap before npm install, should have been in above instructions. – Andy Ray May 04 '15 at 22:30
  • 2
    I use the `depcheck` package installed globally to check what packages are not being used. Then I go to the package-json and remove the unused packages. After those two steps, I run `npm prune` and everything ends right. – Luis Martins Feb 08 '18 at 04:33
  • I replaced `uuid` with `uuidv4` in `package.json`, ran `npm install`, `npm prune`, noticed `uuid` still in `package-lock.json`, removed that, ran `npm prune`, saw it removed, ran `npm install`, and it returned to `package-lock.json` as it's a dependency of `uuidv4` i guess. – Cees Timmerman Jan 06 '20 at 14:06
  • @Darkhogg _Recent npm versions do this automatically_ When doing what? Running `npm install`? – Nils Lindemann Dec 31 '21 at 06:08
  • 1
    @NilsLindemann Yes, exactly. I've added a clarification in the post, thank you. – Darkhogg Jan 04 '22 at 12:11
  • `npm install --production` is working exactly and it also removing unwanted and global packages along with dev dependencies. – Raviteja Mar 17 '22 at 11:11
  • Have no idea why 'npm prune' removes my typescript folder in node_modules ... So, just take my disk space npm. – StoneLam Apr 19 '23 at 06:26
379

If you're not worried about a couple minutes time to do so, a solution would be to rm -rf node_modules and npm install again to rebuild the local modules.

Pyrce
  • 8,296
  • 3
  • 31
  • 46
  • 128
    It would be nice if people stopped downvoting this without comment.. it's a valid strategy to resetting a node project dependencies as an alternative to the accepted answer. If you damaged a node_modules sub-directory contents (easy to do with sym-linked dependencies) or if you've had additional changes like node or npm version bumps prune will not properly cleanup the node_modules folder but this answer will. – Pyrce Jan 12 '16 at 19:06
  • 60
    Rebuilding `node_modules` also verifies the `package.json` file describes a reproducible dependency graph. Removing and re-installing your `node_modules` is basically a deploy test. – joemaller Jan 24 '16 at 18:26
  • 2
    @joemaller Not necessarily, most deployment workflows have, either implicitly or explicitly, some kind of cache. If a package is already installed and fits the specification, it's kept. Removing then reinstalling will bump that package(s) to the latest version that matches. – Darkhogg Mar 09 '16 at 14:15
  • 14
    `npm prune` didn't help one iota, but this did. My problem was a broken symlink. – Eirik Birkeland Apr 22 '16 at 00:34
  • 1
    What about peer dependencies? I think the the objective is to remove all obsolete dependencies, but not removing the whole node_modules and re-installing all peer dependencies again. – Chung Apr 24 '16 at 12:00
  • 11
    Under many non-ideal circumstances that's currently infeasible with npm. Also the question definitely did not specify some constraint on repeated work or additional fetching, just how to achieve the end goal. This answer satisfies the question as stated, despite what others may want beyond that goal. – Pyrce May 04 '16 at 18:41
  • 9
    a handy one liner is `rm -rf node_modules && npm install` punch it in walk away come back. Life is good. – Chris Sprance Sep 11 '17 at 23:18
  • This answer is good enough for John Resig: https://twitter.com/jeresig/status/916729473814417408 – JDB Sep 07 '18 at 21:29
  • 2
    @Anoop.P.A Downvoting (anonymously) is an intended and appreciated thing. https://stackoverflow.com/help/why-vote Voting without a good reason is not appreciated. – Yunnosch Feb 28 '20 at 05:27
  • 1
    This is the best way. It is a better tested use-case for npm and anecdotally faster too. Other options (namely `npm prune`) can leave the modules in a weird state, causing hangs and failures down the line. – Chris Oct 17 '21 at 10:09
27

You can use npm-prune to remove extraneous packages.

npm prune [[<@scope>/]<pkg>...] [--production] [--dry-run] [--json]

This command removes "extraneous" packages. If a package name is provided, then only packages matching one of the supplied names are removed.

Extraneous packages are packages that are not listed on the parent package's dependencies list.

If the --production flag is specified or the NODE_ENV environment variable is set to production, this command will remove the packages specified in your devDependencies. Setting --no-production will negate NODE_ENV being set to production.

If the --dry-run flag is used then no changes will actually be made.

If the --json flag is used then the changes npm prune made (or would have made with --dry-run) are printed as a JSON object.

In normal operation with package-locks enabled, extraneous modules are pruned automatically when modules are installed and you'll only need this command with the --production flag.

If you've disabled package-locks then extraneous modules will not be removed and it's up to you to run npm prune from time-to-time to remove them.

Use npm-dedupe to reduce duplication

npm dedupe
npm ddp

Searches the local package tree and attempts to simplify the overall structure by moving dependencies further up the tree, where they can be more effectively shared by multiple dependent packages.

For example, consider this dependency graph:

a
+-- b <-- depends on c@1.0.x
|    `-- c@1.0.3
`-- d <-- depends on c@~1.0.9
     `-- c@1.0.10

In this case, npm-dedupe will transform the tree to:

 a
 +-- b
 +-- d
 `-- c@1.0.10

Because of the hierarchical nature of node's module lookup, b and d will both get their dependency met by the single c package at the root level of the tree.

The deduplication algorithm walks the tree, moving each dependency as far up in the tree as possible, even if duplicates are not found. This will result in both a flat and deduplicated tree.

Igor Litvinovich
  • 2,436
  • 15
  • 23
  • I have MORE items in my node_modules folder **after** running npm dedupe. Sigh! – Neville Nov 08 '19 at 15:22
  • does remove and uninstall mean the same thing when it comes to using prune? I ran a prune instance with a `--production` flag. But my package.json file never udpated. – klewis Feb 18 '21 at 16:18
  • prune removes those files that present in the node_modules folder but not listed as any package's dependency list. If the --production flag is specified or the NODE_ENV environment variable is set to production, this command will remove the packages specified in your devDependencies. – Igor Litvinovich Feb 19 '21 at 17:28
6

You can run npx depcheck to get the list of dependencies and devDependencies that are not being used in the project.

Then you can run npm uninstall pkg1 pkg2 and so on to remove the dependencies.

Or you can also remove the dependencies from package.json and reinstall the packages after deleting node_modules and package-lock.json

SahilSea
  • 69
  • 1
  • 1