【问题标题】:Find unused npm packages in package.json在 package.json 中查找未使用的 npm 包
【发布时间】:2014-05-05 17:23:25
【问题描述】:

有没有办法确定您的 package.json 文件中是否有不再需要的包?

例如,当我试用一个包并随后评论或删除代码,但忘记卸载它时,我最终得到了几个可以删除的包。

确定一个包是否可以安全删除的有效方法是什么?

【问题讨论】:

    标签: node.js npm dependencies package.json


    【解决方案1】:

    检查未使用的依赖项

    npm install depcheck -g
    depcheck
    

    检查过时的库

    npm outdated
    

    【讨论】:

      【解决方案2】:

      这里的许多答案都是如何找到未使用的物品。

      我想自动删除它们

      选项 1:

      1. 安装此节点项目。
       $ npm install -g typescript tslint tslint-etc
      

      1. 在根目录下,添加一个新文件 tslint-imports.json
      {
        "extends": [
          "tslint-etc"
        ],
        "rules": {
          "no-unused-declaration": true
        }
      }
      

      1. 运行此操作,风险自负,进行备份:)
      $ tslint --config tslint-imports.json --fix --project .
      

      选项 2:根据@Alex

      npx depcheck --json | jq '.dependencies[]' | xargs -L1 npm rm
      

      【讨论】:

      • 但这只会从 js 文件中删除。但你仍然很好。
      • npx depcheck --json | jq '.dependencies[]' | xargs -L1 npm rm怎么样
      • tslint 自 2019 年起已弃用
      【解决方案3】:

      除非我对gombosgnMo 的脚本有误解。这是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"
      
      

      【讨论】:

        【解决方案4】:

        在 Yarn 2.x 及以上版本中,使用:

        yarn dlx depcheck
        

        yarn dlx 旨在执行可能已作为全局包与 yarn 1.x 一起安装的一次性脚本。管理系统范围的包超出了纱线的范围。为了反映这一点,yarn global 已被删除。

        来源:https://yarnpkg.com/getting-started/migration#use-yarn-dlx-instead-of-yarn-global

        【讨论】:

          【解决方案5】:

          如果你想选择站在哪个巨人的肩膀上

          这里是生成 npm 可用选项的简短列表的链接;它过滤关键字unused packages

          https://www.npmjs.com/search?q=unused%20packages

          为什么我的回答只是一个链接?

          通常我不会只提供链接。这个问题值得一个时间敏感度较低的答案。该解决方案依赖于最新的软件。推荐一个可能已经停止维护的特定软件(这里有一些建议的情况)几乎没有用。帮助人们找到最新的东西似乎是合适的。

          【讨论】:

            【解决方案6】:

            您可以使用名为 depcheck 的 npm 模块(至少需要 Node 10 版本)。

            1. 安装模块:

               npm install depcheck -g
              
               or
              
               yarn global add depcheck
              
            2. 运行它并找到未使用的依赖项:

               depcheck
              

            这种方法的好处是您不必记住findgrep 命令。

            不安装运行,请使用npx

            npx depcheck 
            

            【讨论】:

            • depcheck-es6 现已合并到 depcheck 中
            • 看起来没什么用。我正在使用标准的 angular2 cli 设置,depcheck 将每个包都列为unused,这是错误的
            • 注意。 depcheck 不考虑 package.json 中指定的脚本中使用的包
            • 只运行一次(无需安装)- 使用 npx: npx depcheck
            • 对我不起作用。它列出了所有未使用的包。
            【解决方案7】:

            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 将带来巨大的加速。
            • 与 depcheck 和衍生产品相比的最佳解决方案。添加--max-procs|-P 32大大提高了速度。
            • 很好的脚本很好地扩展了原始脚本,但是在大型反应应用程序上它变得无法使用(甚至 xargs -P 选项)。重新组织文件搜索并共享一个应该产生相同输出的版本,但不需要以相同的顺序。
            【解决方案8】:

            我们可以为此目的使用下面的 npm 模块:

            https://www.npmjs.com/package/npm-check-unused

            【讨论】:

            • 它揭示了一些未使用的但也使用过的,我猜仍然有帮助 :-) 它不理解 webpack 加载器 ;-)
            【解决方案9】:

            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_modulesbuild 文件夹(或任何你想要的)。第三行包含允许的扩展名,您可以在此处添加更多内容,例如JSX 或 JSON 文件。

            函数将读取依赖类型。

            首先是cats package.json。然后,jq 获取所需的依赖组。 ({} + 的存在是为了在文件中没有对等依赖项的情况下不会引发错误。)

            之后,sed 提取引号之间的部分,即包名。 -n.../p 告诉它从 jq 的 JSON 输出中打印匹配的部分而不是其他任何内容。然后我们将这个包名列表读入while循环。

            RES 是包名在引号中出现的次数。现在是import/require ...'package'/"package"。它适用于大多数情况。

            然后我们简单地计算结果行数然后打印结果。

            注意事项:

            • 不会在不同的导入中找到文件,例如tsconfig.json 文件(lib 选项)
            • 只有^USEDUNUSED 文件,您必须手动grep
            • 对于大型项目来说速度很慢 - shell 脚本通常不能很好地扩展。但希望您不会运行这么多次。

            【讨论】:

            • 编辑器有时会导致导入换行成多行。此脚本是否会捕获“import”或“require”与“from“PACKAGE_NAME””位于不同行的语句?换句话说,它会忽略 import 或 require 语句中的空格吗?
            【解决方案10】:

            还有一个包叫npm-check

            npm-检查

            检查过时、不正确和未使用的依赖项。

            它非常强大并且正在积极开发。它的一个功能是检查未使用的依赖项 - 对于这一部分,它使用另一个答案中提到的 depcheck 模块。

            【讨论】:

            • 似乎给我的结果与 depcheck 相同。看起来它甚至使用 depcheck 来查找未使用的依赖项。
            • npm outdated检查并列出当前、通缉和最新的软件包版本。但是没有未使用的软件包列表。
            • 看起来也没什么用。我正在使用标准的角度设置,这也将每个包都列为未使用,这同样是错误的
            • 现在似乎有点过时了。它现在包括高严重性漏洞......
            【解决方案11】:

            如果您使用的是类似 Unix 的操作系统(Linux、OSX 等),那么您可以结合使用 findegrep 来搜索包含您的包名称的 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
            • 显然使用这种方法我们没有在我们的 React 应用程序中使用反应模块:D
            猜你喜欢
            • 2012-04-23
            • 2018-08-13
            • 2021-11-18
            • 2018-02-21
            • 2018-01-25
            • 2012-03-18
            • 2019-07-08
            • 2015-10-06
            相关资源
            最近更新 更多