2016-06-15 64 views
1

我的設置如下:NPM全球安裝不鏈接二進制

  • 流浪機中有一個web項目
  • 需要提供一個全球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": { 
    } 
} 

既然不能正確地在網絡上安裝這些模塊目錄中,因爲存在與同步文件夾和npm有關的已知問題,因此我想將它們全局安裝。 沒有傷害,因爲它是一個專用的虛擬機,只有一個Web應用程序。

所以我做的:

sudo npm install -g

後來我嘗試使用bower,這是行不通的,因爲它沒有得到新公共管理過程中鏈接安裝。

當我做 sudo npm install -g [email protected]

我在做什麼錯,它工作正常?

回答

1

好的,我發現,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內創建鏈接。 這是因爲當建立了錯誤時,npm檢查他們擁有哪個父文件夾。如果它不是/usr/lib/node_modules,它將不會全局鏈接。

爲了便於比較,我現在正在運行npm install -g [email protected]的結果,會產生這個文件夾結構:

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

在安裝NPM將實現bower/usr/lib/node_modules和鏈接全球的父文件夾。

這是背後的整個巫術。 我還沒有找到任何解釋這種特定行爲的網站,但我想這是爲了防止與全局安裝的二進制文件混淆的依賴關係。

僅供說明:節點模塊的全局文件夾可能有所不同。 /usr/只是我的前綴。

我試圖通過使用腳本來解決這個問題。我發現關於它的偉大的教程,但由於失去了隱私瀏覽:/

我建議,包括你在package.json像這樣的scripts部分所需要的命令:

{ 
    "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": { 
    } 
} 

之前你尖叫: Nooo,究竟是什麼,完整的路徑缺失,考慮到這一點。 當您使用npm run bower腳本運行命令時,npm包含$ PATH的.bin文件夾,以便可以找到二進制文件。 魔術在其最好:)

我希望我可以幫助一些人偶然遇到同樣的問題:)

0

如果你的意思是你試圖安裝在package.json全球npm install -g依賴關係...這不是它如何工作。 package.json是專門用於定義本地安裝的軟件包。這是所需模塊的清單,可以與項目一起騎行,從而使整個項目規模在運輸過程中更小(即,您不必在回購中包含node_modules等)。

-g標誌用於單獨安裝的全局程序包,通常用於命令行實用程序之類的東西。如果項目中的每個模塊都安裝在全球範圍內,那麼您的情況就不會有真正的問題,但在其他情況下,這種情況將會是一件壞事。

所以你沒有做錯任何事情,只是不是npm如何工作的安裝。

但是,您可以使用npm腳本來定義預安裝或安裝後步驟,該步驟基本上可以運行-g安裝。這是額外的工作,但是如果你擁有這個項目,並且你將會做很多事情......這可能是一個很好的自動化方法。