讀懂package.json -- 依賴管理

npm作爲Javascript項目的包管理工具,因爲其與Node.js的緊密配合(npm和Node.js出自一人之手),目前已經基本沒有競爭對手。javascript

包管理工具要解決的主要問題就是依賴包的安裝,在Javascript項目中,包的依賴關係是由package.json給出的,這篇文件將介紹package.json中描述的依賴信息。java

依賴管理

在package.json中,有以下幾項涉及到依賴包的描述:node

  • dependenciesreact

    項目中使用到的包,但不包括測試所使用的包
  • devDependenciesgit

    主要是在測試時使用的包,也包括一些代碼編譯的包,好比將coffee-script編譯爲javascript。也就是說在僅僅使用該項目的時候(而不進行測試等環節),不須要安裝的包能夠放在devDependencies中github

  • peerDependenciesweb

    若是改項目須要指明一些有協做關係的包的版本時,使用peerDependencies。這裏使用了協做,而不是依賴,是我我的的理解。peerDependencies並非必須安裝的包,但若是一旦要安裝,就要符合要求。好比react-dom的package.json中有以下的描述:npm

    "peerDependencies": {
        "react": "^15.6.1"
       },

    peerDependencies至少打消了一些顧慮,好比react生態中用到的一些包在升級的時候會不會不匹配?json

  • optionalDependencies數組

    若是有一些依賴包即便安裝失敗,項目仍然可以運行或者但願npm繼續運行,就可使用optionalDependencies。另外optionalDependencies會覆蓋dependencies中的同名依賴包,因此不要在兩個地方都寫。

  • bundledDependencies/bundleDependencies

    若是在打包發佈的使用但願一些依賴包也出如今最終的包裏,那麼能夠將包的名字放在bundledDependencies,bundledDependencies的值是一個字符串數組,如:

    "name": "awesome-web-framework",
    "version": "1.0.0",
    "bundledDependencies": [
        'renderized', 'super-streams'
       ]

    npm pack會將renderized super-streams放入生成的包awesome-web-framework-1.0.0.tgz中,而且在npm install awesome-web-framework-1.0.0.tgz時,renderized super-streams也會被一同安裝。

這些項的內容形式都是同樣的(除了bundledDependencies),只是做用不一樣,如:

"dependencies": {
    "base62": "~0.1.1",
    "commoner": "~0.7.0",
    "esprima": "https://github.com/facebook/esprima/tarball/ca28795124d45968e62a7b4b336d23a053ac3a84",
    "recast": "~0.4.8",
    "source-map": "~0.1.22"
  }

key就是項目的名詞,而value能夠有多種形式

  • version,遵循semver

  • 一個tarball的url

  • 一個git url

  • 本地路徑

關於semver會在另外一篇文章中介紹(先挖個坑)。

依賴樹

不一樣於不少語言的依賴管理,npm使用的是依賴樹。也就是說每一個依賴包會有一套本身指定的(在package.json中說明的)依賴包,而不會和其餘包共享。
例如,mod-a依賴mod-b@1.0.0,mod-c依賴mod-b@2.0.0,而如今有一個項目依賴mod-a和mod-c,那麼最終安裝的依賴包以下:

├─┬ node_modules
│ ├─┬ mod-a
│ │ ├── mod-b@1.0.0
│ ├─┬ mod-c
│ │ ├── mod-b@2.0.0

而Node.js在加載依賴包的時候會處理這個問題。之因此文章最開始說npm和Node.js的緊密合做也是這個緣由。

使用依賴樹來管理包帶來了一個明顯的好處,不用處理依賴衝突的問題。這個問題在早期的Java項目中比較常見,而在使用了Maven和Gradle以後,狀況有所緩解,但只能減輕同一個包多個版本被放入發佈的包中這種狀況,仍然沒法解決依賴衝突這個根本問題。

依賴樹也有一些缺點:

  • 代碼量增長。因爲不能共享相同的包(在npm v3中,嘗試着共享相同版本的庫,但仍是比較弱),致使最終打包的時候有同一個庫的多個版本的代碼出如今最終包中。

  • 潛在的運行時衝突。以上面的例子爲例,可能有些時候,mod-b的兩個版本沒法同時運行,而這隻有在運行或者測試的時候才能被發現。

但願以上的介紹可以幫助你更好的理解npm的依賴管理。

相關文章
相關標籤/搜索