【发布时间】:2014-05-05 17:23:25
【问题描述】:
有没有办法确定您的 package.json 文件中是否有不再需要的包?
例如,当我试用一个包并随后评论或删除代码,但忘记卸载它时,我最终得到了几个可以删除的包。
确定一个包是否可以安全删除的有效方法是什么?
【问题讨论】:
标签: node.js npm dependencies package.json
有没有办法确定您的 package.json 文件中是否有不再需要的包?
例如,当我试用一个包并随后评论或删除代码,但忘记卸载它时,我最终得到了几个可以删除的包。
确定一个包是否可以安全删除的有效方法是什么?
【问题讨论】:
标签: node.js npm dependencies package.json
这里的许多答案都是如何找到未使用的物品。
选项 1:
$ npm install -g typescript tslint tslint-etc
{
"extends": [
"tslint-etc"
],
"rules": {
"no-unused-declaration": true
}
}
$ tslint --config tslint-imports.json --fix --project .
选项 2:根据@Alex
npx depcheck --json | jq '.dependencies[]' | xargs -L1 npm rm
【讨论】:
npx depcheck --json | jq '.dependencies[]' | xargs -L1 npm rm怎么样
除非我对gombosg 和nMo 的脚本有误解。这是nMo 脚本扩展的更快版本,默认为“查找”,但可以轻松修改为使用“fd”进行查找功能。
变化在于它首先查找所有相关文件,然后一次性从所有相关文件中 grep 包,而不是逐个文件库。
并发可以控制,默认为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"
【讨论】:
yarn dlx depcheck
yarn dlx 旨在执行可能已作为全局包与 yarn 1.x 一起安装的一次性脚本。管理系统范围的包超出了纱线的范围。为了反映这一点,yarn global 已被删除。
来源:https://yarnpkg.com/getting-started/migration#use-yarn-dlx-instead-of-yarn-global
【讨论】:
这里是生成 npm 可用选项的简短列表的链接;它过滤关键字unused packages
https://www.npmjs.com/search?q=unused%20packages
通常我不会只提供链接。这个问题值得一个时间敏感度较低的答案。该解决方案依赖于最新的软件。推荐一个可能已经停止维护的特定软件(这里有一些建议的情况)几乎没有用。帮助人们找到最新的东西似乎是合适的。
【讨论】:
您可以使用名为 depcheck 的 npm 模块(至少需要 Node 10 版本)。
安装模块:
npm install depcheck -g
or
yarn global add depcheck
运行它并找到未使用的依赖项:
depcheck
这种方法的好处是您不必记住find 或grep 命令。
要不安装运行,请使用npx:
npx depcheck
【讨论】:
depcheck 将每个包都列为unused,这是错误的
npx depcheck
gombosg 的脚本比 npm-check 好得多。
我稍微修改了一下,所以node_modules中的devdependencies也会被发现。
示例 sass 从未使用过,但在 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"
原始脚本的结果:
--------------------------
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
以及修改后的:
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
【讨论】:
-P 32 开关添加到您的 xargs 将带来巨大的加速。
--max-procs|-P 32大大提高了速度。
我们可以为此目的使用下面的 npm 模块:
【讨论】:
fiskeben 写道:
缺点是它不是全自动的,即它不会从 package.json 中提取包名并检查它们。您需要自己为每个包执行此操作。
如果由于某种原因depcheck 无法正常工作,让我们让 Fiskeben 的答案自动化! (例如,我使用 Typescript 进行了尝试,但它给出了不必要的解析错误)
解析package.json我们可以使用软件jq。下面的 shell 脚本需要一个目录名来开始。
#!/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"
首先它会创建两个临时文件,我们可以在其中缓存包名和文件。
它以find 命令开头。第一行和第二行使它忽略 node_modules 和 build 文件夹(或任何你想要的)。第三行包含允许的扩展名,您可以在此处添加更多内容,例如JSX 或 JSON 文件。
函数将读取依赖类型。
首先是cats package.json。然后,jq 获取所需的依赖组。 ({} + 的存在是为了在文件中没有对等依赖项的情况下不会引发错误。)
之后,sed 提取引号之间的部分,即包名。 -n 和 .../p 告诉它从 jq 的 JSON 输出中打印匹配的部分而不是其他任何内容。然后我们将这个包名列表读入while循环。
RES 是包名在引号中出现的次数。现在是import/require ...'package'/"package"。它适用于大多数情况。
然后我们简单地计算结果行数然后打印结果。
注意事项:
tsconfig.json 文件(lib 选项)^USED 和UNUSED 文件,您必须手动grep。【讨论】:
如果您使用的是类似 Unix 的操作系统(Linux、OSX 等),那么您可以结合使用 find 和 egrep 来搜索包含您的包名称的 require 语句:
find . -path ./node_modules -prune -o -name "*.js" -exec egrep -ni 'name-of-package' {} \;
如果您搜索整个require('name-of-package') 语句,请记住使用正确类型的引号:
find . -path ./node_modules -prune -o -name "*.js" -exec egrep -ni 'require("name-of-package")' {} \;
或
find . -path ./node_modules -prune -o -name "*.js" -exec egrep -ni "require('name-of-package')" {} \;
缺点是它不是全自动的,即它不会从package.json 中提取包名并检查它们。您需要自己为每个包执行此操作。由于package.json 只是JSON,这可以通过编写一个使用child_process.exec 为每个依赖项运行此命令的小脚本来解决。并使其成为一个模块。并将其添加到 NPM 存储库中...
【讨论】:
.jsx 文件和.ts 文件等怎么样:D