npm 與 package.json 快速入門

    npm 是前端開發普遍使用的包管理工具,以前使用 Weex 時看了阮一峯前輩的文章瞭解了一些,此次結合官方文章總結一下,加深下理解吧!javascript

讀完本文你將瞭解:html

 

 

什麼是 npm?

這裏寫圖片描述

官方文檔中對它的介紹是:前端

npm makes it easy for JavaScript developers to share and reuse code, and it makes it easy to update the code that you’re sharing.vue

即: npm 是一個包管理器,它讓 JavaScript 開發者分享、複用代碼更方便(有點 maven 的感受哈)。html5

在程序開發中咱們經常須要依賴別人提供的框架,寫 JS 也不例外。這些能夠重複的框架代碼被稱做包(package)或者模塊(module),一個包能夠是一個文件夾裏放着幾個文件,同時有一個叫作 package.json的文件。java

一個網站裏一般有幾十甚至上百個 package,分散在各處,一般會將這些包按照各自的功能進行劃分(相似咱們安卓開發中的劃分子模塊),可是若是重複造一些輪子,不如上傳到一個公共平臺,讓更多的人一塊兒使用、參與這個特定功能的模塊。node

而 npm 的做用就是讓咱們發佈、下載一些 JS 輪子更加方便。webpack

咱們能夠去官方網站 https://www.npmjs.com/ 瀏覽、搜索想要的輪子,也能夠直接在命令行中 search 一下意中輪。git

這裏寫圖片描述

使用 npm 後咱們能夠很是方便地查看依賴的輪子是否有更新、是否須要下載新版本。github

如今咱們知道 npm 是幹什麼的了。當人們提及 「npm」 時,可能在說三個東西:

  1. 一個網站,就是前面提到用於搜索 JS 模塊的網站:https://www.npmjs.com/
  2. 一個倉庫,保存着人們分享的 JS 模塊的大數據庫
  3. 命令行裏的客戶端,開發者使用它來管理、安裝、發佈模塊

只要開發者發佈某個模塊到倉庫中,其餘人就能夠從 npm 網站或者命令行中下載、使用它了!

安裝 npm

npm 是依附於 node.js 的,咱們能夠去它的官網 https://nodejs.org/en/download/ 下載安裝 node.js。

下載好 node.js, npm 也就有了,使用 npm -v 查看安裝的 npm 版本:

zhangshixin$ node -v
v6.10.0
  • 1
  • 2

更新 npm

npm 更新地可比 node 勤快多了,所以你下載的 node 附帶的 npm 版本可能不是最新的,你可使用以下命令下載最新 npm:

npm install npm@latest -g
  • 1

其中 install 不用介紹了,就是安裝,後面的 npm@latest 就是 <packageName>@<version> 的格式,咱們在下載其餘模塊時也是這個格式。-g 表明全局安裝。

package.json 文件

package.json 文件很是重要,所以須要單獨一小節介紹。

管理本地安裝 npm 包的最好方式就是建立 package.json 文件。

一個 package.json 文件能夠有如下幾點做用:

  1. 做爲一個描述文件,描述了你的項目依賴哪些包
  2. 容許咱們使用 「語義化版本規則」(後面介紹)指明你項目依賴包的版本
  3. 讓你的構建更好地與其餘開發者分享,便於重複使用

package.json 如何建立

使用 npm init 便可在當前目錄建立一個 package.json 文件:

這裏寫圖片描述

如圖所示,輸入 npm init 後會彈出一堆問題,咱們能夠輸入對應內容,也可使用默認值。在回答一堆問題後輸入 yes 就會生成圖中所示內容的 package.json 文件。

若是嫌回答這一大堆問題麻煩,能夠直接輸入 npm init --yes 跳過回答問題步驟,直接生成默認值的 package.json 文件:

這裏寫圖片描述

package.json 的內容

package.json 文件至少要有兩部份內容:

  1. 「name」 
    • 所有小寫,沒有空格,可使用下劃線或者橫線
  2. 「version」 
    • x.x.x 的格式
    • 符合「語義化版本規則」

好比:

{
  "name": "shixinzhang-demo-package",
  "version": "1.0.0"
}
  • 1
  • 2
  • 3
  • 4

其餘內容:

  • description:描述信息,有助於搜索
  • main: 入口文件,通常都是 index.js
  • scripts:支持的腳本,默認是一個空的 test
  • keywords:關鍵字,有助於在人們使用 npm search 搜索時發現你的項目
  • author:做者信息
  • license:默認是 MIT
  • bugs:當前項目的一些錯誤信息,若是有的話

咱們能夠爲 init 命令設置一些默認值,好比:

> npm set init.author.email "shixinzhang2016@gmail.com"
> npm set init.author.name "shixinzhang"
> npm set init.license "MIT"
  • 1
  • 2
  • 3

注意: 
若是 package.json 中沒有 description 信息,npm 使用項目中的 README.md 的第一行做爲描述信息。這個描述信息有助於別人搜索你的項目,所以建議好好寫 description 信息。

指定依賴的包

咱們須要在 package.json 文件中指定項目依賴的包,這樣別人在拿到這個項目時纔可使用 npm install 下載。

包有兩種依賴方式:

  1. dependencies:在生產環境中須要用到的依賴
  2. devDependencies:在開發、測試環境中用到的依賴

舉個例子:

{
    "name": "my-weex-demo",
    "version": "1.0.0",
    "description": "a weex project",
    "main": "index.js",
    "scripts": {
        "build": "weex-builder src dist",
        "build_plugin": "webpack --config ./tools/webpack.config.plugin.js --color",
        "dev": "weex-builder src dist -w",
        "serve": "serve -p 8080"
    },
    "keywords": [
        "weex"
    ],
    "author": "fkysly@gmail.com",
    "license": "MIT",
    "devDependencies": {
        "babel-core": "^6.14.0",
        "babel-loader": "^6.2.5",
        "babel-preset-es2015": "^6.18.0",
        "vue-loader": "^10.0.2",
        "eslint": "^3.5.0",
        "serve": "^1.4.0",
        "webpack": "^1.13.2",
        "weex-loader": "^0.3.3",
        "weex-builder": "^0.2.6"
    },
    "dependencies": {
        "weex-html5": "^0.3.2",
        "weex-components": "*"
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

Semantic versioning(語義化版本規則)

https://docs.npmjs.com/getting-started/semantic-versioning

dependencies 的內容,以 "weex-html5": "^0.3.2" 爲例,咱們知道 key 是依賴的包名稱,value 是這個包的版本。那版本前面的 ^ 或者版本直接是一個 * 是什麼意思呢?

這就是 npm 的 「Semantic versioning」,簡稱」Semver」,中文含義即「語義化版本規則」。

在安卓開發中咱們有過這樣的經驗:有時候依賴的包升級後大改版,以前提供的接口不見了,這對使用者的項目可能形成極大的影響。

所以咱們在聲明對某個包的依賴時須要指明是否容許 update 到新版本,什麼狀況下容許更新。

這就須要先了解 npm 包提供者應該注意的版本號規範。

若是一個項目打算與別人分享,應該從 1.0.0 版本開始。之後要升級版本應該遵循如下標準:

  • 補丁版本:解決了 Bug 或者一些較小的更改,增長最後一位數字,好比 1.0.1
  • 小版本:增長了新特性,同時不會影響以前的版本,增長中間一位數字,好比 1.1.0
  • 大版本:大改版,沒法兼容以前的,增長第一位數字,好比 2.0.0

瞭解了提供者的版本規範後, npm 包使用者就能夠針對本身的須要填寫依賴包的版本規則。

做爲使用者,咱們能夠在 package.json 文件中寫明咱們能夠接受這個包的更新程度(假設當前依賴的是 1.0.4 版本):

  • 若是隻打算接受補丁版本的更新(也就是最後一位的改變),就能夠這麼寫: 
    • 1.0
    • 1.0.x
    • ~1.0.4
  • 若是接受小版本的更新(第二位的改變),就能夠這麼寫: 
    • 1
    • 1.x
    • ^1.0.4
  • 若是能夠接受大版本的更新(天然接受小版本和補丁版本的改變),就能夠這麼寫: 
    • *
    • x

小結一下:總共三種版本變化類型,接受依賴包哪一種類型的更新,就把版本號準確寫到前一位。

安裝 package

使用 npm 安裝 package 有兩種方式:本地(當前項目路徑)安裝 或者 全局安裝。

你選擇哪一種安裝方式取決於你將如何使用這個包:

  • 若是你只是想在當前項目裏用 require() 加載使用,那你能夠安裝到本地 
    • npm install 默認就是安裝到本地的
  • 若是你想要在命令行裏直接使用,好比 grunt CLI,就須要安裝到全局了

若是在你的項目裏有 package.json 文件,運行 npm install 後它會查找文件中列出的依賴包,而後下載符合語義化版本規則的版本。

npm install 默認會安裝 package.json 中 dependencies 和 devDependencies 裏的全部模塊。

若是想只安裝 dependencies 中的內容,可使用 --production 字段:

npm install --production
  • 1

本地安裝 package

npm 使用下面的命令下載一個包:

npm install <package_name>
  • 1

後面就是要安裝包的名稱。這個命令會在當前目錄建立一個 node_modules 目錄,而後下載咱們指定的包到這個目錄中。

舉個例子:

zhangshixindeMacBook-Pro:publish-pkg zhangshixin$ npm install lodash
zhangshixindeMacBook-Pro:publish-pkg zhangshixin$ ls
index.js        package-lock.json
node_modules        package.json
zhangshixindeMacBook-Pro:publish-pkg zhangshixin$ ls node_modules/
lodash
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

下載後的項目文件夾:

這裏寫圖片描述

安裝指定版本:

npm install 默認安裝最新版本,若是想要安裝指定版本,能夠在庫名稱後加 @版本號

$ npm install sax@latest
$ npm install sax@0.1.1
$ npm install sax@">=0.1.0 <0.2.0"
  • 1
  • 2
  • 3

若是當前項目有 package.json 文件,下載包時會下載這個文件中指定的版本; 
若是當前項目中沒有 package.json 文件,就會下載指定包的最新版本。

有時下載會報錯:npm install error saveError ENOENT: no such file or directory, open '/Users/zhangshixin/package.json'

解決辦法: 
- 在目錄下執行 npm init 建立 package.json,輸入初始化信息 
- 而後再執行下載命令

安裝參數 --save 和 --save -dev

添加依賴時咱們能夠手動修改 package.json 文件,添加或者修改 dependencies devDependencies 中的內容便可。

另外一種更酷的方式是用命令行,在使用 npm install 時增長 --save 或者 --save -dev 後綴:

  • npm install <package_name> --save 表示將這個包名及對應的版本添加到 package.json的 dependencies
  • npm install <package_name> --save-dev 表示將這個包名及對應的版本添加到 package.json的 devDependencies

使用下載好的包

下載後 node_modules 文件夾中有要使用的包,咱們就可使用其中的代碼了。

好比在 Node.js 項目中,咱們能夠用 require(XXX) 引入它。

舉個例子: 
建立一個 index.js 文件,寫入以下代碼:

這裏寫圖片描述

在使用 require('lodash') 後引入了 lodash 庫,而後調用了它的 without() 方法,這個方法能夠去除第一個數組參數中與第二個參數重複的數據。

保存這個文件後,使用 node index.js 運行這個文件,成功的話就能夠獲得運行結果;若是以前安裝失敗,可能就會遇到這個錯誤:

module.js:340
    throw err;
          ^
Error: Cannot find module 'lodash'
  • 1
  • 2
  • 3
  • 4

這時你須要在這個目錄下從新運行 npm install lodash 安裝。

更新本地 package

有時候咱們想知道依賴的包是否有新版本,可使用 npm outdated 查看,若是發現有的包有新版本,就可使用 npm update <package-name> 更新它,或者直接 npm update 更新全部:

這裏寫圖片描述

上圖中,咱們在輸入 npm update 後發現本地的 lodash 模塊還不是最新的,這是爲何呢?

原來,npm update 的工做過程是這樣的:

  1. 先到遠程倉庫查詢最新版本
  2. 而後對比本地版本,若是本地版本不存在,或者遠程版本較新
  3. 查看 package.json 中對應的語義版本規則
  4. 若是當前新版本符合語義規則,就更新,不然不更新

一開始我本地的 package.json 的依賴是這樣的:

"dependencies": {
    "lodash": "^3.1.0"
  }
  • 1
  • 2
  • 3

根據前面的介紹咱們能夠知道,這表示只接受小版本或者補丁版本的更新,所以在執行了一次 npm update 後它變成了這樣:

"dependencies": {
    "lodash": "^3.10.1"
  }
  • 1
  • 2
  • 3

第二位升到了最高,可是沒法更新第一位,所以沒法更新到最新的 4.17.4。

因此我須要把它修改爲:

"dependencies": {
    "lodash": "*"
  }
  • 1
  • 2
  • 3

這表示任何版本的更新都接受,而後再執行 npm update,就發現更新成功了:

這裏寫圖片描述

小結一下:

執行 npm outdated 後能夠看到有三個版本號:

這裏寫圖片描述

第一個是當前 node_modules 中該模塊的版本,第二個是 package.json 文件中聲明的版本,第三個是遠程倉庫最新的版本。

只有當前模塊版本低於遠程,package.json 中的版本語義規則知足狀況,才能更新成功。

卸載本地 package

卸載一個本地 package 很簡單,npm uninstall <package-name> 便可:

這裏寫圖片描述

官方文檔說輸入 npm uninstall --save lodash 才能在刪除項目的同時移除 package.json 中對它的依賴。但我沒加 --save 也達到了同樣的效果,一臉懵逼。

卸載後再 ls node_modules/ 查看目錄下,發現沒有東西,刪除成功。

全局安裝 package

若是你想要直接在命令行中使用某個包,好比 jshint ,你能夠全局安裝它。

全局安裝比本地安裝多了個 -g:

npm install -g <package-name>
  • 1

以 jshint 爲例,全局安裝命令是:

npm install -g jshint
  • 1

這裏寫圖片描述

安裝後可使用 npm ls -g --depth=0 查看安裝在全局第一層的包。

全局安裝的權限問題

在全局安裝時可能會遇到 EACCES 權限問題,解決辦法辦法有以下 3 種:

1.sudo npm install -g jshint,使用 sudo 簡單粗暴,可是治標不治本

2.修改 npm 全局默認目錄的權限

先獲取 npm 全局目錄:npm config get prefix,通常都是 /usr/local; 
而後修改這個目錄權限爲當前用戶:

sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
  • 1

3.使用其餘包管理器幫你解決這個問題

實在懶得弄能夠直接卸載 node,而後使用 Homebrew 重裝 node:

brew install node
  • 1

Homebrew 會幫咱們處理好權限的問題。

更新全局的 package

想知道哪些包須要更新,可使用 npm outdated -g --depth=0,而後使用 npm update -g <package>更新指定的包:

這裏寫圖片描述

要更新全部全局包,可使用 npm update -g,能夠發現對比本地的,只是多了個 -g

不過官方說在 2.6.1 如下的 npm ,直接使用 npm update -g 並不安全,由於它會遞歸地更新全部全局依賴。

這種狀況下可使用 npm-check ,貼一張它的截圖:

這裏寫圖片描述

Github 地址:https://github.com/dylang/npm-check

卸載全局 package

一句搞定:npm uninstall -g <package>

其餘命令

npm run

部分摘自 阮一峯的 NPM 教程

npm 還能夠直接運行 package.json 中 scripts 指定的腳本:

{
  "name": "demo",
  "scripts": {
    "lint": "jshint **.js",
    "test": "mocha test/"
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

npm run 是 npm run-script 的縮寫。

命令行輸入 npm run lint 或者 npm run-script lint 就會執行 jshint **.js 。

npm run 會建立一個Shell,執行指定的命令,並臨時將node_modules/.bin加入PATH 變量,這意味着本地模塊能夠直接運行。

package.json 中的 scripts 執行的腳本是本地項目內 node_modules -> .bin 內的腳本。

"scripts": {
        "build": "weex-builder src dist",
        "build_plugin": "webpack --config ./tools/webpack.config.plugin.js --color",
        "dev": "weex-builder src dist -w",
        "serve": "serve -p 8080"
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

這裏寫圖片描述

直接運行 npm run 會列出當前項目的 package.json 中 scripts 屬性下的全部腳本命令。

npm install from github

npm install 也能夠直接從 github 下載:

$ npm install git://github.com/package/path.git
$ npm install git://github.com/package/path.git#0.1.0
  • 1
  • 2

npm info

npm info <package-name> 能夠查看指定包的信息:

這裏寫圖片描述

npm adduser

npm adduser 用於在npmjs.com註冊一個用戶:

$ npm adduser
Username: YOUR_USER_NAME
Password: YOUR_PASSWORD
Email: YOUR_EMAIL@domain.com
  • 1
  • 2
  • 3
  • 4

npm home/repo

npm home <package-name>命令能夠打開指定模塊的主頁; 
npm repo <package-name>命令則是打開指定模塊的代碼倉庫。

npm prune

prune 即「修剪」的意思。

npm prune 能夠檢查出當前項目的 node_modules目錄中,沒有在 package.json裏提到的模塊。

npm publish

如今水平還不夠,等寫出能夠複用的 JS 代碼後,咱們就能夠將它發佈到 npm 倉庫上,相似 Github 的提交。

這部分主要摘自阮一峯的 NPM 教程

要想發佈,首先須要使用 npm adduser向 npmjs.com申請用戶名(固然去官網也能夠)。

接着使用 npm login 在命令行中登陸。

登陸之後,就可使用 npm publish命令發佈。

$ npm publish
  • 1
  • 2

若是當前模塊是一個beta版,好比1.3.1-beta.3,那麼發佈的時候須要使用tag參數,將其發佈到指定標籤,默認的發佈標籤是latest。

$ npm publish --tag beta
  • 1
  • 2

若是發佈私有模塊,模塊初始化的時候,須要加上scope參數。只有npm的付費用戶才能發佈私有模塊。

$ npm init --scope=<yourscope>
  • 1
  • 2

若是你的模塊是用ES6寫的,那麼發佈的時候,最好轉成ES5。首先,須要安裝Babel。

$ npm install --save-dev babel-cli@6 babel-preset-es2015@6
  • 1
  • 2

而後,在package.json裏面寫入build腳本。

"scripts": {
  "build": "babel source --presets babel-preset-es2015 --out-dir distribution",
  "prepublish": "npm run build"
}
  • 1
  • 2
  • 3
  • 4
  • 5

運行上面的腳本,會將source目錄裏面的ES6源碼文件,轉爲distribution目錄裏面的ES5源碼文件。

國內鏡像

不翻的話有時候 npm 比較卡,可使用國內的淘寶鏡像 cnpm: https://npm.taobao.org

cnpm 支持 npm 除了 publish 以外的全部命令。

總結

這裏寫圖片描述

通過這麼一番總結,總算能夠說 npm 入門了。

相關文章
相關標籤/搜索