如何从相关版本中获取准确的最新 npm 版本?

How can I get the exact latest npm version from a relative version?

我希望能够获得与相关语义版本匹配的 npm 的最新发布版本。

例如,我想运行这样的东西:

npm -v 6.12.x

然后 return 匹配的确切最新版本:

=> 6.12.1

我已经探索了一些可用的文档和命令,或者认为这可以通过 npm 实现,但我还没有看到任何不安装另一个全局依赖项的工作。

简短回答: npm 没有提供完全满足您要求的内置功能。

然而,npm 确实提供了 npm-view 命令。它的文档说明如下:

If a version range is provided, then data will be printed for every matching version of the package. This will show which version of jsdom was required by each matching version of yui3:

npm view yui3@'>0.5.4' dependencies.jsdom.

下面给出的两个解决方案演示了 npm view 命令的输出如何可以 parsed/manipulated 来满足您的要求(无需安装另一个全局依赖项)。


解决方案 A:*仅限 Nix 平台 (Linux/MacOS...)

因此,可以借助一些额外的 Bash 实用程序来解析输出,从而达到您的要求。

考虑运行以下复合命令:

npm view npm@'6.12.x' version | tail -n 1 | cut -d "'" -f2

说明

下面对上述复合命令的组成部分进行解释:

  1. npm view npm@'6.12.x' version

    这部分使用npm view命令来return给定范围内的所有版本,即6.12.x

    运行 这些部分独立将打印以下内容到您的控制台:

    npm@6.12.0 '6.12.0'
    npm@6.12.1 '6.12.1'
    
  2. | tail -n 1

    然后使用 -n 1 选项将先前显示的结果通过管道传输到 tail,以便只打印最后一行。

    运行:

    npm view npm@'6.12.x' version | tail -n 1
    

    打印:

    npm@6.12.1 '6.12.1'

  3. | cut -d "'" -f2

    然后使用 -d 选项将先前显示的结果通过管道传输到 cut,并指定单引号作为分隔符。 -f2 部分然后选择第二项。

    运行 完整的复合命令:

    npm view npm@'6.12.x' version | tail -n 1 | cut -d "'" -f2
    

    打印您想要的结果:

    6.12.1

波浪符 (~) 和插入符 (^) 范围。

您还可以使用上述复合命令指定波浪号或插入符范围。

例子:

  • 指定波浪号范围:

    npm view npm@'~4.0.0' version | tail -n 1 | cut -d "'" -f2
                  ^^^^^^
    

    打印:

    4.0.5

  • 指定插入符范围:

    npm view npm@'^4.0.0' version | tail -n 1 | cut -d "'" -f2
                  ^^^^^^
    

    打印:

    4.6.1

简化用法:

如果你打算 运行 命令经常在 *nix 那么我建议:

  1. 运行 下面的复合命令:

    echo $'\n'"npmv() { npm view \"npm@${1}\" version | tail -n 1 | cut -d \"'\" -f2; }" >> ~/.bash_profile
    

    这会将 shell function 添加到 .bash_profile 文件的内容中,即它会添加一个新行:

    npmv() { npm view "npm@" version | tail -n 1 | cut -d "'" -f2; }

  2. 然后当你创建一个新会话时(即创建新的window,或者重新启动终端),以后你可以简单地运行:

    npmv 6.12.x
    

    它很简洁,更类似于您问题中给出的示例命令。

注意: 如果您已经在系统上全局安装了名为 npmv 的 npm 包,请为 [=280 选择一个不同的名称=] function/command 以避免任何冲突。


解决方案 B:跨平台(Windows/Linux/macOS...)

如果您正在使用 Windows,或想要跨平台解决方案(即 运行 在 Windows、Linux 上成功实现的解决方案,以及macOS...),你需要利用 nodejs 来实现你的要求。

考虑运行以下复合命令:

node -e "var res = require('child_process').execSync('npm view npm@"\"6.12.x\"" version', {encoding: 'utf-8'}).split('\n').filter(Boolean); if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } console.log(res.replace(/[']/g, '')); }"

是的,我同意它与 解决方案 A :)

相比有点冗长

说明

下面对上述复合命令的组成部分进行解释:

  1. node -e "..."

    我们调用 node 并且使用 nodejs 命令行选项 -e 来评估给定的内联 JavaScript.

  2. var res = require('child_process').execSync('npm view npm@"\"6.12.x\"" version', {encoding: 'utf-8'})

    给定的 node.js 脚本 (JavaScript) 的这一部分 shells-根据 解决方案 Anpm view 使用相同的 npm view 命令=244=],即 npm view npm@"\"6.12.x\"" version,使用 execSync().

  3. .split('\n').filter(Boolean);

    npm view 命令的结果使用字符串的 split() 方法从字符串转换为数组 - 结果的每一行基本上都被换行符 \n 分割这样每行输出就成为数组中的一个元素。

    .filter(Boolean) 部分从数组中删除由 npm view 命令打印的附加尾随空行生成的空元素。

  4. if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } ... }

    这里我们利用一些条件if..else语句来确保我们从数组中获得所需的项目。

  5. console.log(res.replace(/[']/g, ''));

    最后我们将结果记录到控制台并使用 replace() 方法删除包含 semver 值的单引号 (')。

语义波浪号 (~) 和插入符 (^) 范围。

根据解决方案 A,您还可以使用上述复合命令指定波浪号或插入符范围。

例子:

  • 指定波浪号范围:

    node -e "var res = require('child_process').execSync('npm view npm@"\"~4.0.0\"" version', {encoding: 'utf-8'}).split('\n').filter(Boolean); if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } console.log(res.replace(/[']/g, '')); }"
                                                                          ^^^^^^
    

    打印:

    4.0.5

  • 指定插入符范围:

    node -e "var res = require('child_process').execSync('npm view npm@"\"^4.0.0\"" version', {encoding: 'utf-8'}).split('\n').filter(Boolean); if (res.length) { if (res.length === 1) { res = res[0]; } else { res = res.pop().split(' ')[1]; } console.log(res.replace(/[']/g, '')); }"
                                                                          ^^^^^^
    

    打印:

    4.6.1