npm全局安装package.json不会链接二进制文件

时间:2016-06-15 18:36:53

标签: npm

我的设置如下:

  • 带有网络项目的流浪机
  • 需要全球可用的bower安装
  • 以下package.json:
{
  "name": "gadada",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "me",
  "dependencies": {
    "bower": "latest",
  },
  "devDependencies": {
  }
}

由于我无法在web目录中正确安装这些模块,因为同步文件夹和npm存在已知问题,我想全局安装它们。 没有伤害,因为它是一个专用的虚拟机,只适用于一个Web应用程序。

所以我这样做:

sudo npm install -g

之后我尝试使用bower,它不起作用,因为它在npm安装期间没有链接。

我这样做很好 sudo npm install -g bower@latest

我做错了什么?

2 个答案:

答案 0 :(得分:2)

好的,我发现,npm不能那样工作。您无法从package.json全局安装依赖命令行工具。 谢谢你指出这一点,@ Matthew Bakaitis

我昨天挖掘了npm代码,发现了一段解释这种行为的代码:

var linkStuff = build.linkStuff = function (pkg, folder, global, didRB, cb) {
  // allow to opt out of linking binaries.
  if (npm.config.get('bin-links') === false) return cb()

  // if it's global, and folder is in {prefix}/node_modules,
  // then bins are in {prefix}/bin
  // otherwise, then bins are in folder/../.bin
  var parent = pkg.name && pkg.name[0] === '@' ? path.dirname(path.dirname(folder)) : path.dirname(folder)
  var gnm = global && npm.globalDir
  var gtop = parent === gnm

  log.info('linkStuff', packageId(pkg))
  log.silly('linkStuff', packageId(pkg), 'has', parent, 'as its parent node_modules')
  if (global) log.silly('linkStuff', packageId(pkg), 'is part of a global install')
  if (gnm) log.silly('linkStuff', packageId(pkg), 'is installed into a global node_modules')
  if (gtop) log.silly('linkStuff', packageId(pkg), 'is installed into the top-level global node_modules')

  shouldWarn(pkg, folder, global, function () {
    asyncMap(
      [linkBins, linkMans, !didRB && rebuildBundles],
      function (fn, cb) {
        if (!fn) return cb()
        log.verbose(fn.name, packageId(pkg))
        fn(pkg, folder, parent, gtop, cb)
      },
      cb
    )
  })
}

在此处找到:https://github.com/npm/npm/blob/master/lib/build.js#L93

正如您在此处所看到的,关于parent变量的评论清楚地指出,只有安装在“根”节点模块文件夹中的软件包才会全局链接,而所有其他软件包将在.bin中链接包文件夹。

为了澄清这种行为,我将给你快速举例。 因此,我运行npm install -g后的结构将是:

/usr/lib/node_modules
| --> npm
| --> gadada

正如我们所看到的,npm创建了一个新的子文件夹调用gadada,这是我在包json中给出的名称。在那里放置依赖关系并在/usr/lib/node_modules/gadada/.bin内创建链接。 这是因为当构建depdencies时,npm检查它们具有哪个父文件夹。如果不是/usr/lib/node_modules,则不会全局链接。

为了比较,我现在运行npm install -g bower@latest的结果会产生这个文件夹结构:

/usr/lib/node_modules
| --> npm
| --> gadada
| --> bower

在安装时,npm会意识到bower的父文件夹是/usr/lib/node_modules并且全局链接。

这是它背后的整个伏都教。 我没有发现任何网站解释这种特殊行为,但我想这是为了防止依赖性乱搞全局二进制文件。

只是为了澄清:节点模块的全局文件夹可能不同。 /usr/只是我的前缀。

我尝试使用`脚本来解决这个问题。我发现了一个很棒的教程,但由于隐私浏览而失去了它:/

我建议在scripts的{​​{1}}部分中包含您需要的命令,如下所示:

package.json

在你尖叫之前:Nooo,到底是什么,缺少完整的路径,考虑一下。 当您使用{ "name": "gadada", "version": "1.0.0", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "bower": "bower" }, "author": "me", "dependencies": { "bower": "latest", }, "devDependencies": { } } 从脚本运行命令时,npm包含$ PATH的npm run bower文件夹,以便可以找到二进制文件。 魔术最精彩:)

我希望我能帮助一些遇到同样问题的人:)

答案 1 :(得分:0)

如果您的意思是尝试使用package.jsonnpm install -g全局安装依赖项...那不是它的工作原理。 package.json专门用于定义本地安装的包。它是可以与项目一起运行的必需模块的清单,允许总体项目大小在传输中更小(即,您不必在回购中包含node_modules等)。

-g标志用于单独安装的全局包,通常用于命令行实用程序。如果项目中的每个模块都是全局安装的,那么你的情况就不会有任何严重的问题,在其他情况下,这样的情况将是一件坏事。

所以你没有做错任何事,这不是npm如何安装。

但是,您可以使用npm脚本来定义基本上运行-g安装的安装前或安装后步骤。这是额外的工作,但是如果你拥有这个项目并且你将会做很多......这可能是一种自动化的好方法。