天天都在使用 npm,但本身明白不少地方仍是不清楚,爲此決定仔細閱讀 npm 的官方文檔,這篇文章講解了 npm 的基本使用方法,後續會講 npm 的一些高級用法。node
雖然前不久出現的 yarn 確實比 npm 快,可是我想 npm 至少還會使用好久,所以有必要詳細瞭解它。react
package.json
中的常見字段package.json
至關因而一個項目的總體描述,其中記錄了該項目的 git 地址,項目簡介,依賴模塊,bug 彙報地址等等信息,現在不少工具都利用 package.json
來存放配置文件,好比 eslint 能夠讀取 package.json
中的 eslintConfig
字段來獲取配置,babel 能夠讀取 babel
字段來獲取配置。webpack
關於 package.json
中每一個字段的定義,請參照官方文檔 package.json,這裏只提到一些很是經常使用的字段。git
包名,這個名字決定了包在 node_modules
中的文件夾名,能夠加上 scope,好比 @att/wxx
,scope 爲 att
,用戶安裝的時候會被安裝在 node_modules/@att/
這個文件夾下。web
該模塊的入口文件,好比 "main": "build/index.js"
,別人在 require 這個包的時候,實際是 require 了項目中的 build/index.js
這個文件。typescript
用來指定可執行文件的名稱和路徑,好比 { "bin" : { "wxx-cli" : "src/cli.js" } }
,這樣用戶在安裝該模塊的時候,npm 會建立一個文件叫作 wxx-cli
放置在 node_modules/.bin
文件下,並將其連接至 src/cli.js
這個文件上。關於此,後面還會詳細講解。express
用來指定一些腳本,也就是人們一般所說的 npm script,這個字段是一個對象,在這裏能夠自定義多個命令,這些命令可使用 npm run 來執行,好比:npm
{ "scripts":{ "build": "webpack", "start": "webpack-dev-server" } }
有了上面這樣的配置,在項目中執行 npm run build
就會執行命令 webpack
,npm script 涉及的東西較多,後面有專門的一章來說它。json
package.json
中的 dependencies
和 devDependencies
分別記錄了該項目在生產環境下依賴的模塊,和在開發環境下依賴的模塊。gulp
好比一個項目使用了 typescript 來開發,在發佈的時候一般要將代碼編譯爲 JavaScript,所以在開發的時候使用的 typescript 就應該放在 devDependencies
,因此在安裝的時候,可使用 npm i typescript --save-dev
來安裝。
另外項目代碼中依賴了一個模塊 qs
來解析 url,爲了讓你的代碼跑起來,這個模塊必須存在,所以,必須將該模塊記錄在 dependencies
中,使用 npm i qs --save
來進行安裝。這樣用戶在運行你的代碼的時候,你代碼中的 require('qs')
纔不至於找不到模塊報錯。
peerDependencies 經常出如今一些插件的 package.json
中,好比一個 react 的第三方組件,它只能用在 react 版本高於 15.0.0 的時候,此時它就應該這樣寫:
{ "peerDependencies": { "react": "15.x" } }
這表示,要想使用我,你必須使用 react 15.0.0 之後的版本,請確保你安裝了 react 15.0.0 之後的版本。
爲何要存在 peerDependencies
呢?
使用 peerDependencies
代表的是,我與另一個模塊協調工做。這有別於依賴於某個模塊,仔細體會,他們之間的差別很微妙。一個插件,可能不會去引用摸個模塊,好比一個 jQuery
插件,它只是在 jQuery.propotype
上添加了一些方法,所以在安裝插件的時候,插件應該是默認你已經安裝了它的宿主模塊。npm3 之後,在執行 npm install
的時候不會安裝 peerDependencies
中的模塊,這是符合 peerDependencies
的設計理念的。
如何使用 peerDependencies
?
若是你的模塊與另一些模塊協同工做,該模塊要想工做,須要用戶已經安裝另一個模塊,好比一個 webpack 的 loader,一個 gulp 的插件,一個 express 的中間件等等。這個時候你須要考慮使用 peerDependencies
。
另外,設置 peerDependencies
的時候 版本範圍要大,試想一下,你的項目中使用了 10 個 react 的第三方組件,這些第三方組件的 peerDependencies
分別是這樣寫的 "react": "15.0.0"
,"react": "15.1.0"
,"react": "15.2.0"
...,這時候會出現什麼狀況?狀況是你沒辦法同時使用這些第三方組件,由於它們限定了要使用某個特定版本的 react,你沒有辦法兼顧全部組件的要求。
當相反,若是版本的限制要求的比較寬泛,好比 "react": ">15.0.0"
表示大於 15.0.0 版本就行了,這樣以來全部的組件均可以融洽相處了。
Ok,上面這些 package.json
中的字段算是最爲常見的了,其餘有些看到單詞就知道是什麼意思了,還有一些不常見,如需瞭解,請參見官方文檔。
package.json
使用 npm init
來建立一個 package.json
,在建立的過程當中要求輸入一些基本信息,若是但願使用默認內容,可使用 npm init --yes
這樣就不須要一步步按回車了。
能夠經過 npm set
來設置默認項,好比 npm set init.author.email "i@example.com"
設置默認郵件。
在安裝模塊的時候一般使用 npm install <package name>
好比 npm install q
,也可使用縮寫 npm i q
,但更多時候當咱們安裝了一個模塊後,一般但願將它記錄下來,將其寫入到 package.json
中,在安裝模塊的時候,能夠經過 --save
和 --save-dev
選項來將一個模塊添加至 dependencies
或 devDependencies
中。
一個模塊的版本號應該形如 1.0.0
,在版本升級的時候,每一位表明着不一樣的變化:
修改 bug,打補丁,應該修改最後一位,好比 1.0.1
新的特性,且不會影響現存的特性,比較小的修改,增長中間一位,好比 1.1.0
大的修改,對現有功能有影響,增長第一位,好比 2.0.0
安裝第三方模塊的時候須要指定其版本號,若是你打開一個既有項目的 package.json
,會看到 ^
, ~
這樣的符號,由於依賴的模塊是在不斷升級的,這些符號表示接受怎樣的升級:
用戶在安裝某個模塊的時候,也會一併安裝該模塊依賴的模塊(存在於 dependencies
中的模塊),這個時候 npm 會安裝最新的知足你版本要求的模塊。看下面詳細說明:
接受微小的升級,bug 修復:1.0 或者 1.0.x 或者 ~1.0.4,這表示在安裝的時候接受最後一位的變化。好比在初次安裝的時候,模塊 A 是 1.0.0 版本,用戶下次安裝的時候 A 模塊已經升級到了 1.0.9,這個時候就會安裝 1.0.9 版本,若是 A 項目的維護者,下次發佈了 1.1.0 那麼,再次安裝的時候依然會安裝 1.0.9。
接受較小的升級,新增特性:1 或者 1.x 或者 ^1.0.4,這表示接受中間位置的變化
接受重大升級:*
或者 x
懂得這個很重要,不少時候這個符號寫的不對,致使依賴模塊升級後,整個項目就跑不起來了。固然了有時候會看到更加複雜的寫法,請參照這裏 semver 瞭解更高級的用法。
依賴的模塊才你開發的過程當中也可能在升級,爲了得到符合你的版本描述的最新版本,能夠在 package.json
所在目錄下執行 npm update
來升級模塊。也能夠經過執行 npm outdated
來獲取當前項目中可升級的模塊的信息。
由於項目變更,不須要使用某個模塊了,這個時候不該該讓他繼續存在於 package.json
中的,沒有使用到,但仍是要被安裝,這顯然是浪費資源,污染環境的作法。使用 npm uninstall loadsh
來卸載一個模塊,不會從 package.json
中刪除該模塊,須要添加 --save
和 --save-dev
來卸載他們。
有兩種模式來安裝模塊 global 和 local,安裝在全局的模塊一般是一些命令行工具,好比 eslint
,能夠將其安裝在全局,在任何目錄下都能使用。可是全局的模塊只能存在一個版本,這也是爲何不少時候一些模塊建議安裝在本地,這樣不一樣的項目可使用不一樣的版本,避免不一樣項目之間的衝突。將一個模塊安裝在全局,只須要加上 -g
選項,好比 npm i eslint -g
。
安裝全局模塊,經常出現一些權限問題,一般是由於當前用戶沒有 npm 全局安裝目錄的寫權限,爲此可使用 chown 來修權限,也能夠直接使用 sudo 來執行 npm install 操做,或者將 npm 默認安裝目錄修改成一個本身具備權限的目錄。這些操做請參考 Fixing npm permissions
升級一個全局模塊,只須要執行 npm update -g <package>
便可,好比 npm update -g gulp
。
很簡單 npm uninstall -g <package>
好比 npm uninstall -g eslint
建立了一個項目,填寫了 package.json,爲了讓本身的代碼讓更多人使用,須要將其發佈到 npm 上面,須要仔細填寫 package.json 中的 description
和 keywords
這些字段的信息將有助於其餘人在 npm 上搜索到該模塊。
爲了將模塊發佈到 npm 上,首先須要建立一個 npm 的帳號,這能夠在 https://npmjs.com/ 上建立帳號,也可使用 npm adduser 在命令行中建立帳號。若是是在網站上註冊的帳號,須要使用 npm login
來登陸。在登陸的時候須要輸入用戶名和密碼,以及你的 E-mail。
登陸完成後執行 npm publish
就能夠發佈模塊了,在發佈模塊以前要確保你的模塊名在當前的 npm 倉庫中是不存在的。另外本地的一些測試文件,一般不須要發佈在 npm 上,這樣用戶在安裝的時候只會下載那些必要的文件,npm 在發佈的時候會忽略掉全部 .gitignore
和 .npmignore
中忽略的文件,一般你應該在 .npmignore
中忽略掉測試文件、文檔等內容,另外要提供一個 README.md
。
對本身的模塊進行了升級之後,須要將更新發布到 npm 上去,這個時候要一樣是使用 npm publish
,可是在此以前要注意更新版本號,你能夠手動更改,也可使用 npm version <update_type>
來更改,這兒的 update_type
能夠是 patch
, minor
, major
使用這三個值,npm 會對應地將版本號的第 3 位、第 2 位、第 1 位加 1,分別表示這次升級有微小改動、有較小改動以及有大幅改動。
有些時候須要建立一個公司內部使用的模塊,或者某個模塊已經有了同名的模塊存在,這個時候能夠用到帶有命名空間的模塊,其名稱形如 @scope/project
,在 npm 上面帶有命名空間的模塊默認是私有的,並且每一個用戶有有一個屬於本身的命名空間也就是 @username
,在 npm 上私有的模塊是要付費的,所以爲了免費地發佈一個帶有命名空間的模塊,須要將該模塊設置爲公開的,只須要在執行 publish
的時候加上 --access=public
選項便可。
在安裝這些帶有命名空間的模塊的時候須要這樣安裝 npm install @scope/project --save
,在項目中引用的時候也要帶上 scope,require('@scope/project')
。
npm 也容許開發着給某個版本打 tag,好比當版本進行到 1.0.9 的時候能夠給他打個 tag 叫作 beta,這個時候用戶可使用 npm i project-name@beta
來安裝這個版本,這等價於 npm i project@1.0.9
使用 npm dist-tag add <package>@<version> tag
來給某個版本打 tag,默認狀況下載 npm publish
的時候 npm 會給當前版本打一個 tag 叫作 latest
,表示這是最新的,可使用 npm publish --tag <tag-name>
來改變默認的 tag。