Reputation: 8411
Is there a way to determine if you have packages in your package.json
file that are no longer needed?
For instance, when trying out a package and later commenting or deleting code, but forgetting to uninstall it, I end up with a couple packages that could be deleted.
What would be an efficient way to determine if a package could safely be deleted?
Upvotes: 703
Views: 453552
Reputation: 1033
fiskeben wrote:
The downside is that it's not fully automatic, i.e. it doesn't extract package names from package.json and check them. You need to do this for each package yourself.
Let's make Fiskeben's answer automated if for whatever reason depcheck
is not working properly! (E.g. I tried it with Typescript and it gave unnecessary parsing errors)
For parsing package.json
we can use the software jq
. The below shell script requires a directory name where to start.
#!/bin/bash
DIRNAME=${1:-.}
cd $DIRNAME
FILES=$(mktemp)
PACKAGES=$(mktemp)
find . \
-path ./node_modules -prune -or \
-path ./build -prune -or \
\( -name "*.ts" -or -name "*.js" -or -name "*.json" \) -print > $FILES
function check {
cat package.json \
| jq "{} + .$1 | keys" \
| sed -n 's/.*"\(.*\)".*/\1/p' > $PACKAGES
echo "--------------------------"
echo "Checking $1..."
while read PACKAGE
do
RES=$(cat $FILES | xargs -I {} egrep -i "(import|require).*['\"]$PACKAGE[\"']" '{}' | wc -l)
if [ $RES = 0 ]
then
echo -e "UNUSED\t\t $PACKAGE"
else
echo -e "USED ($RES)\t $PACKAGE"
fi
done < $PACKAGES
}
check "dependencies"
check "devDependencies"
check "peerDependencies"
First it creates two temporary files where we can cache package names and files.
It starts with the find
command. The first and second line make it ignore the node_modules
and build
folders (or whatever you want). The third line contains allowed extensions, you can add more here e.g. JSX or JSON files.
A function will read dependendy types.
First it cat
s the package.json
. Then, jq
gets the required dependency group. ({} +
is there so that it won't throw an error if e.g. there are no peer dependencies in the file.)
After that, sed
extracts the parts between the quotes, the package name. -n
and .../p
tells it to print the matching parts and nothing else from jq
's JSON output. Then we read this list of package names into a while
loop.
RES
is the number of occurrences of the package name in quotes. Right now it's import
/require
... 'package'
/"package"
. It does the job for most cases.
Then we simply count the number of result lines then print the result.
Caveats:
tsconfig.json
files (lib
option)grep
manually for only ^USED
and UNUSED
files.Upvotes: 14
Reputation: 2257
I decided for knip after doing some research and PoCs because it is a tool-set to keep the code clean and also dependencies up-to-date. Even though the tool is new, the community and fundamental direction in the architecture is going pretty well.
Upvotes: 2
Reputation: 11542
npm install depcheck -g
depcheck
npm outdated
Upvotes: 84
Reputation: 563
For checking unused dependencies, libraries and unimported files
npx unimported
you will get result something like that
Upvotes: 18
Reputation: 7429
Many of the answer here are how to only find unused items. What if... I wanted to AUTOmatically -- a) find + b) Remove the unused items?
Option 2, below seems to be the newer way.
Option 1:
$ npm install -g typescript tslint tslint-etc
{
"extends": [
"tslint-etc"
],
"rules": {
"no-unused-declaration": true
}
}
$ tslint --config tslint-imports.json --fix --project .
Option 2 (per @Alex & @JacopKane suggestions, thanks):
// newer one line option
npx depcheck --json | jq '.dependencies[]' | xargs -L1 npm rm
// or
npm uninstall $(npx depcheck --oneline)
Upvotes: 18
Reputation: 19
I've created a package unused-package (https://www.npmjs.com/package/unused-package) which returns any unused packages or if package is devDependency but installed as normal dependecy
create a file and add this code to to your file
const check = require("unused-package");
check({ entries: ['entry path to your code'] }).then((res) => {
console.log(res) // list of packages returned by library
});
one ADVANTAGE of usused-package over depcheck package is unused-package supports multiple entry path.
Upvotes: 1
Reputation: 431
Unless I've misunderstood something about the scripts by gombosg and nMo. Here's a faster version of nMo script-extensions with defaulting to 'find', but can be easily modified to use 'fd' for find functionality.
Changes are that it first finds all relevant files and then grep packages from all relevant files on one go and not a file-by-file bases.
Concurrency can be controlled and defaults to 8.
#!/bin/bash
DIRNAME=${1:-.}
cd "$DIRNAME"
FILES=$(mktemp)
PACKAGES=$(mktemp)
export NUMCONCURRENT=8
function findCmd {
startPath=${1:-.}
find "$startPath" \
-path ./node_modules -prune -or \
-path ./build -prune -or \
\( -name "*.ts" -or -name "*.js" -or -name "*.json" \) -print
}
# use fd
# https://github.com/sharkdp/fd
function findCmd_fd {
startPath=${1:-.}
fd -t f '(js|ts|json)$' "$startPath"
}
function check {
cat package.json \
| jq "{} + .$1 | keys" \
| sed -n 's/.*"\(.*\)".*/\1/p' > "$PACKAGES"
echo "--------------------------"
echo "Checking $1..."
findCmd > "$FILES"
while read PACKAGE
do
#echo "node_modules/${PACKAGE}"
if [ -d "node_modules/${PACKAGE}" ]; then
findCmd node_modules/${PACKAGE} >> $FILES
fi
done < $PACKAGES
export FILES
export SQ="'"
xargs -P ${NUMCONCURRENT:-1} -r -a "$PACKAGES" -I[] bash -c '
PACKAGE="[]"
RES=$(cat "$FILES" | xargs -r egrep -i "(import|require|loader|plugins|${PACKAGE}).*[\"${SQ}](${PACKAGE}|.?\d+)[\"${SQ}]" | wc -l)
if [ $RES = 0 ]
then
echo -e "UNUSED\t\t $PACKAGE"
else
echo -e "USED ($RES)\t $PACKAGE"
fi
'
[ -f "$PACKAGES" ] && rm "$PACKAGES"
[ -f "$FILES" ] && rm "$FILES"
}
check "dependencies"
check "devDependencies"
check "peerDependencies"
Upvotes: 4
Reputation: 11636
yarn dlx depcheck
yarn dlx is designed to execute one off scripts that may have been installed as global packages with yarn 1.x. Managing system-wide packages is outside of the scope of yarn. To reflect this, yarn global has been removed.
Source: https://yarnpkg.com/getting-started/migration#use-yarn-dlx-instead-of-yarn-global
Upvotes: 4
Reputation: 4046
here is a link to generate a short list of options available to npm; it filters on the keywords unused packages
https://www.npmjs.com/search?q=unused%20packages
Typically I wouldn't provide just a link. This question deserves a less time-sensitive answer. The solution relies on up-to-date software. Recommending a specific piece of software that may have stopped being maintained (the case with some of the recommendations here) is of little use. Helping people find something current seems appropriate.
Upvotes: 1
Reputation: 23653
You can use an npm module called depcheck (requires at least version 10 of Node).
Install the module:
npm install depcheck -g
or
yarn global add depcheck
Run it and find the unused dependencies:
depcheck
The good thing about this approach is that you don't have to remember the find
or grep
command.
To run without installing use npx
:
npx depcheck
Upvotes: 874
Reputation: 263
The script from gombosg is much better then npm-check.
I have modified a little bit, so devdependencies in node_modules will also be found.
example sass
never used, but needed in sass-loader
#!/bin/bash
DIRNAME=${1:-.}
cd $DIRNAME
FILES=$(mktemp)
PACKAGES=$(mktemp)
# use fd
# https://github.com/sharkdp/fd
function check {
cat package.json \
| jq "{} + .$1 | keys" \
| sed -n 's/.*"\(.*\)".*/\1/p' > $PACKAGES
echo "--------------------------"
echo "Checking $1..."
fd '(js|ts|json)$' -t f > $FILES
while read PACKAGE
do
if [ -d "node_modules/${PACKAGE}" ]; then
fd -t f '(js|ts|json)$' node_modules/${PACKAGE} >> $FILES
fi
RES=$(cat $FILES | xargs -I {} egrep -i "(import|require|loader|plugins|${PACKAGE}).*['\"](${PACKAGE}|.?\d+)[\"']" '{}' | wc -l)
if [ $RES = 0 ]
then
echo -e "UNUSED\t\t $PACKAGE"
else
echo -e "USED ($RES)\t $PACKAGE"
fi
done < $PACKAGES
}
check "dependencies"
check "devDependencies"
check "peerDependencies"
Result with original script:
--------------------------
Checking dependencies...
UNUSED jquery
--------------------------
Checking devDependencies...
UNUSED @types/jquery
UNUSED @types/jqueryui
USED (1) autoprefixer
USED (1) awesome-typescript-loader
USED (1) cache-loader
USED (1) css-loader
USED (1) d3
USED (1) mini-css-extract-plugin
USED (1) postcss-loader
UNUSED sass
USED (1) sass-loader
USED (1) terser-webpack-plugin
UNUSED typescript
UNUSED webpack
UNUSED webpack-cli
USED (1) webpack-fix-style-only-entries
and the modified:
Checking dependencies...
USED (5) jquery
--------------------------
Checking devDependencies...
UNUSED @types/jquery
UNUSED @types/jqueryui
USED (1) autoprefixer
USED (1) awesome-typescript-loader
USED (1) cache-loader
USED (1) css-loader
USED (2) d3
USED (1) mini-css-extract-plugin
USED (1) postcss-loader
USED (3) sass
USED (1) sass-loader
USED (1) terser-webpack-plugin
USED (16) typescript
USED (16) webpack
USED (2) webpack-cli
USED (2) webpack-fix-style-only-entries
Upvotes: 18
Reputation: 11
We can use the below npm module for this purpose:
https://www.npmjs.com/package/npm-check-unused
Upvotes: 1
Reputation: 473763
There is also a package called npm-check
:
npm-check
Check for outdated, incorrect, and unused dependencies.
It is quite powerful and actively developed. One of it's features it checking for unused dependencies - for this part it uses the depcheck
module mentioned in the other answer.
Upvotes: 205
Reputation: 3467
If you're using a Unix like OS (Linux, OSX, etc) then you can use a combination of find
and egrep
to search for require statements containing your package name:
find . -path ./node_modules -prune -o -name "*.js" -exec egrep -ni 'name-of-package' {} \;
If you search for the entire require('name-of-package')
statement, remember to use the correct type of quotation marks:
find . -path ./node_modules -prune -o -name "*.js" -exec egrep -ni 'require("name-of-package")' {} \;
or
find . -path ./node_modules -prune -o -name "*.js" -exec egrep -ni "require('name-of-package')" {} \;
The downside is that it's not fully automatic, i.e. it doesn't extract package names from package.json
and check them. You need to do this for each package yourself. Since package.json
is just JSON this could be remedied by writing a small script that uses child_process.exec
to run this command for each dependency. And make it a module. And add it to the NPM repo...
Upvotes: 6