Node.js npm模塊管理器

2021-09-15 16:26 更新

簡(jiǎn)介

npm有兩層含義。一層含義是Node.js的開放式模塊登記和管理系統(tǒng),網(wǎng)址為http://npmjs.org。另一層含義是Node.js默認(rèn)的模塊管理器,是一個(gè)命令行下的軟件,用來安裝和管理node模塊。

npm不需要單獨(dú)安裝。在安裝node的時(shí)候,會(huì)連帶一起安裝npm。但是,node附帶的npm可能不是最新版本,最好用下面的命令,更新到最新版本。

$ npm install npm@latest -g

上面的命令之所以最后一個(gè)參數(shù)是npm,是因?yàn)閚pm本身也是Node.js的一個(gè)模塊。

node安裝完成后,可以用下面的命令,查看一下npm的幫助文件。

# npm命令列表
$ npm help

# 各個(gè)命令的簡(jiǎn)單用法
$ npm -l

下面的命令分別查看npm的版本和配置。

$ npm -v
$ npm config list -l

npm info

npm info命令可以查看每個(gè)模塊的具體信息。比如,查看underscore模塊信息的命令是:

$ npm info underscore
{ name: 'underscore',
  description: 'JavaScript\'s functional programming helper library.',
  'dist-tags': { latest: '1.5.2', stable: '1.5.2' },
  repository:
   { type: 'git',
     url: 'git://github.com/jashkenas/underscore.git' },
  homepage: 'http://underscorejs.org',
  main: 'underscore.js',
  version: '1.5.2',
  devDependencies: { phantomjs: '1.9.0-1' },
  licenses:
   { type: 'MIT',
     url: 'https://raw.github.com/jashkenas/underscore/master/LICENSE' },
  files:
   [ 'underscore.js',
     'underscore-min.js',
     'LICENSE' ],
  readmeFilename: 'README.md'}

上面命令返回一個(gè)JavaScript對(duì)象,包含了underscore模塊的詳細(xì)信息。這個(gè)對(duì)象的每個(gè)成員,都可以直接從info命令查詢。

$ npm info underscore description
JavaScript's functional programming helper library.

$ npm info underscore homepage
http://underscorejs.org

$ npm info underscore version
1.5.2

npm search

向npm倉(cāng)庫(kù)搜索某個(gè)模塊,使用search命令(可使用正則搜索)。

$ npm search <搜索詞>

如果不加搜索詞,npm search默認(rèn)返回npm倉(cāng)庫(kù)的所有模塊。

npm list

npm list命令列出當(dāng)前目錄安裝的所有模塊。如果使用global參數(shù),就是列出全局安裝的模塊。

$ npm list
$ npm -global list

npm install

Node模塊采用npm install命令安裝。每個(gè)模塊可以“全局安裝”,也可以“本地安裝”。兩者的差異是模塊的安裝位置,以及調(diào)用方法。

“全局安裝”指的是將一個(gè)模塊直接下載到Node的安裝目錄中,各個(gè)項(xiàng)目都可以調(diào)用?!氨镜匕惭b”指的是將一個(gè)模塊下載到當(dāng)前目錄的node_modules子目錄,然后只有在當(dāng)前目錄和它的子目錄之中,才能調(diào)用這個(gè)模塊。一般來說,全局安裝只適用于工具模塊,比如npm和grunt。

默認(rèn)情況下,npm install命令是“本地安裝”某個(gè)模塊。

$ npm install <package name>

npm也支持直接輸入github地址。

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

運(yùn)行上面命令后,模塊文件將下載到當(dāng)前目錄的node_modules子目錄。

使用global參數(shù),可以“全局安裝”某個(gè)模塊。global參數(shù)可以被簡(jiǎn)化成g參數(shù)。

$ sudo npm install -global [package name]
$ sudo npm install -g [package name]

install命令總是安裝模塊的最新版本,如果要安裝模塊的特定版本,可以在模塊名后面加上@和版本號(hào)。

$ npm install sax@latest
$ npm install sax@0.1.1
$ npm install sax@">=0.1.0 <0.2.0"

install命令可以使用不同參數(shù),指定所安裝的模塊屬于哪一種性質(zhì)的依賴關(guān)系,即出現(xiàn)在packages.json文件的哪一項(xiàng)中。

  • --save:模塊名將被添加到dependencies,可以簡(jiǎn)化為參數(shù)-S。
  • --save-dev: 模塊名將被添加到devDependencies,可以簡(jiǎn)化為參數(shù)-D。
$ npm install sax --save
$ npm install node-tap --save-dev
# 或者
$ npm install sax -S
$ npm install node-tap -D

npm install默認(rèn)會(huì)安裝dependencies字段和devDependencies字段中的所有模塊,如果使用production參數(shù),可以只安裝dependencies字段的模塊。

$ npm install --production
# 或者
$ NODE_ENV=production npm install

一旦安裝了某個(gè)模塊,就可以在代碼中用require命令調(diào)用這個(gè)模塊。

var backbone = require('backbone')

console.log(backbone.VERSION)

語(yǔ)義版本(SemVer)

npm采用”語(yǔ)義版本“管理軟件包。所謂語(yǔ)義版本,就是指版本號(hào)為a.b.c的形式,其中a是大版本號(hào),b是小版本號(hào),c是補(bǔ)丁號(hào)。

一個(gè)軟件發(fā)布的時(shí)候,默認(rèn)就是 1.0.0 版。如果以后發(fā)布補(bǔ)丁,就增加最后一位數(shù)字,比如1.0.1;如果增加新功能,且不影響原有的功能,就增加中間的數(shù)字(即小版本號(hào)),比如1.1.0;如果引入的變化,破壞了向后兼容性,就增加第一位數(shù)字(即大版本號(hào)),比如2.0.0。

npm允許使用特殊符號(hào),指定所要使用的版本范圍,假定當(dāng)前版本是1.0.4。

  • 只接受補(bǔ)丁包:1.0 或者 1.0.x 或者 ~1.0.4
  • 只接受小版本和補(bǔ)丁包:1 或者 1.x 或者 ^1.0.4
  • 接受所有更新:* or x

對(duì)于~和^,要注意區(qū)分。前者表示接受當(dāng)前小版本(如果省略小版本號(hào),則是當(dāng)前大版本)的最新補(bǔ)丁包,后者表示接受當(dāng)前大版本的最新小版本和最新補(bǔ)丁包。

~2.2.1 // 接受2.2.1,不接受2.3.0
^2.2.1 // 接受2.2.1和2.3.0

~2.2 // 接受2.2.0和2.2.1,不接受2.3.0
^2.2 // 接受2.2.0、2.2.1和2.3.0

~2 // 接受2.0.0、2.1.0、2.2.0、2.2.1和2.3.0
^2 // 接受2.0.0、2.1.0、2.2.0、2.2.1和2.3.0

還可以使用數(shù)學(xué)運(yùn)算符(比如>, = or <=等),指定版本范圍。

>2.1
1.0.0 - 1.2.0
>1.0.0-alpha
>=1.0.0-rc.0 <1.0.1
^2 <2.2 || > 2.3

注意,如果使用連字號(hào),它的兩端必須有空格。如果不帶空格,會(huì)被npm理解成預(yù)發(fā)布的tag,比如1.0.0-rc.1。

npm update,npm uninstall

npm update 命令可以升級(jí)本地安裝的模塊。

npm update [package name]

加上global參數(shù),可以升級(jí)全局安裝的模塊。

npm update -global [package name]

npm uninstall 命令,刪除本地安裝的模塊。

npm uninstall [package name]

加上global參數(shù),可以刪除全局安裝的模塊。

sudo npm uninstall [package name] -global

npm shrinkwrap

對(duì)于一個(gè)項(xiàng)目來說,通常不會(huì)寫死依賴的npm模塊的版本。比如,開發(fā)時(shí)使用某個(gè)模塊的版本是1.0,那么等到用戶安裝時(shí),如果該模塊升級(jí)到1.1,往往就會(huì)安裝1.1。

但是,對(duì)于開發(fā)者來說,有時(shí)最好鎖定所有依賴的版本,防止模塊升級(jí)帶來意想不到的問題。但是,由于模塊自己還依賴別的模塊,這一點(diǎn)往往很難做到。舉例來說,項(xiàng)目依賴A模塊,A模塊依賴B模塊。即使寫死A模塊的版本,但是B模塊升級(jí)依然可能導(dǎo)致不兼容。

npm shrinkwrap命令就是用來徹底鎖定所有模塊的版本。

$ npm shrinkwrap

運(yùn)行上面這個(gè)命令以后,會(huì)在項(xiàng)目目錄下生成一個(gè)npm-shrinkwrap.json文件,里面包含當(dāng)前項(xiàng)目用到的所有依賴(包括依賴的依賴,以此類推),以及它們的準(zhǔn)確版本,也就是當(dāng)前正在使用的版本。

只要存在npm-shrinkwrap.json文件,下一次用戶使用npm install命令安裝依賴的時(shí)候,就會(huì)安裝所有版本完全相同的模塊。

如果執(zhí)行npm shrinkwrap的時(shí)候,加上參數(shù)dev,還可以記錄devDependencies字段中模塊的準(zhǔn)確版本。

$ npm shrinkwrap --dev

npm prune

npm prune命令與npm shrinkwrap配套使用。

使用npm shrinkwrap的時(shí)候,有時(shí)可能存在某個(gè)已經(jīng)安裝的模塊不在dependencies字段內(nèi)的情況,這時(shí)npm shrinkwrap 就會(huì)報(bào)錯(cuò)。

npm prune命令可以移除所有不在dependencies字段內(nèi)的模塊。所有指定模塊名,則移除單個(gè)模塊。

$ npm prune
$ npm package <package name>

npm run

package.json文件有一項(xiàng)scripts,用于指定腳本命令,供npm直接調(diào)用。

{
  "name": "myproject",
  "devDependencies": {
    "jshint": "latest",
    "browserify": "latest",
    "mocha": "latest"
  },
  "scripts": {
    "lint": "jshint **.js",
    "test": "mocha test/"
  }
}

上面代碼中,scripts指定了兩項(xiàng)命令lint和test。命令行輸入npm run lint,就會(huì)執(zhí)行jshint **.js,輸入npm run test,就會(huì)執(zhí)行mocha test/。npm內(nèi)置了兩個(gè)命令簡(jiǎn)寫,npm test等同于執(zhí)行npm run lint,npm start等同于執(zhí)行npm run start。

npm run會(huì)創(chuàng)建一個(gè)shell,執(zhí)行指定的命令,并將node_modules/.bin加入PATH變量,這意味著本地模塊可以直接運(yùn)行。也就是說,npm run lint直接運(yùn)行jshint **.js即可,而不用./node_modules/.bin/jshint **.js

如果直接運(yùn)行npm run不給出任何參數(shù),就會(huì)列出scripts屬性下所有命令。

Available scripts in the user-service package:
  lint
     jshint **.js
  test
    mocha test/

下面是另一個(gè)package.json文件的例子。

"scripts": {
  "watch": "watchify client/main.js -o public/app.js -v",
  "build": "browserify client/main.js -o public/app.js",
  "start": "npm run watch & nodemon server.js",
  "test": "node test/all.js"
},

上面代碼在scripts項(xiàng),定義了四個(gè)別名,每個(gè)別名都有對(duì)應(yīng)的腳本命令。

npm run watch
npm run build
npm run start
npm run test

其中,start和test屬于特殊命令,可以省略run。

npm start
npm test

如果希望一個(gè)操作的輸出,是另一個(gè)操作的輸入,可以借用Linux系統(tǒng)的管道命令,將兩個(gè)操作連在一起。

"build-js": "browserify browser/main.js | uglifyjs -mc > static/bundle.js"

但是,更方便的寫法是引用其他npm run命令。

"build": "npm run build-js && npm run build-css"

上面的寫法是先運(yùn)行npm run build-js,然后再運(yùn)行npm run build-css,兩個(gè)命令中間用&&連接。如果希望兩個(gè)命令同時(shí)平行執(zhí)行,它們中間可以用&連接。

下面是一個(gè)流操作的例子。

"devDependencies": {
  "autoprefixer": "latest",
  "cssmin": "latest"
},

"scripts": {
  "build:css": "autoprefixer -b 'last 2 versions' < assets/styles/main.css | cssmin > dist/main.css"
}

寫在scripts屬性中的命令,也可以在node_modules/.bin目錄中直接寫成bash腳本。

#!/bin/bash

cd site/main;
browserify browser/main.js | uglifyjs -mc > static/bundle.js

假定上面的腳本文件名為build.sh,并且權(quán)限為可執(zhí)行,就可以在scripts屬性中引用該文件。

"build-js": "bin/build.sh"

npm run為每條命令提供了pre和post兩個(gè)鉤子(hook)。以npm run lint為例,執(zhí)行這條命令之前,npm會(huì)先查看有沒有定義prelint和postlint兩個(gè)鉤子,如果有的話,就會(huì)先執(zhí)行npm run prelint,然后執(zhí)行npm run lint,最后執(zhí)行npm run postlint。所有命令都是這樣,包括npm test(即實(shí)際存在npm run pretest、npm run testnpm run posttest三條命令)。如果執(zhí)行過程出錯(cuò),就不會(huì)執(zhí)行排在后面的命令,即如果pretest命令執(zhí)行出錯(cuò),就不會(huì)接著執(zhí)行 test和posttest命令。不能在pre命令之前再加pre,即prepretest命令不起作用。另外,還可以為一些內(nèi)部命令指定pre和post的鉤子:install、uninstall、publish、update。

"scripts": {
  "lint": "jshint **.js",
  "build": "browserify index.js > myproject.min.js",
  "test": "mocha test/",

  "prepublish": "npm run build # also runs npm run prebuild",
  "prebuild": "npm run test # also runs npm run pretest",
  "pretest": "npm run lint"
}

npm run命令還可以添加參數(shù)。

"scripts": {
  "test": "mocha test/"
}

上面代碼指定npm test,實(shí)際運(yùn)行mocha test/??梢栽?code>npm test命令后面加上參數(shù),比如npm run test -- anothertest.js,實(shí)際運(yùn)行的是mocha test/ anothertest.js。

npm link

一般來說,每個(gè)項(xiàng)目都會(huì)在項(xiàng)目目錄內(nèi),安裝所需的模塊文件。也就是說,各個(gè)模塊是局部安裝。但是有時(shí)候,我們希望模塊是一個(gè)符號(hào)鏈接,連到外部文件,這時(shí)候就需要用到npm link命令。

為了理解npm link,請(qǐng)?jiān)O(shè)想這樣一個(gè)場(chǎng)景。你開發(fā)了一個(gè)模塊myModule,目錄為src/myModule,你自己的項(xiàng)目myProject要用到這個(gè)模塊,項(xiàng)目目錄為src/myProject。每一次,你更新myModule,就要用npm publish命令發(fā)布,然后切換到項(xiàng)目目錄,使用npm update更新模塊。這樣顯然很不方便,如果我們可以從項(xiàng)目目錄建立一個(gè)符號(hào)鏈接,直接連到模塊目錄,就省去了中間步驟,項(xiàng)目可以直接使用最新版的模塊。

先在模塊目錄(src/myModule)下運(yùn)行npm link命令。

src/myModule$ npm link

上面的命令會(huì)在npm的全局模塊目錄內(nèi)(比如/usr/local/lib/node_modules/),生成一個(gè)符號(hào)鏈接文件,該文件的名字就是package.json文件中指定的文件名。

/usr/local/lib/node_modules/myModule -> src/myModule

然后,切換到你需要放置該模塊的項(xiàng)目目錄,再次運(yùn)行npm link命令,并指定模塊名。

src/myProject$ npm link myModule

上面命令等同于生成了本地模塊的符號(hào)鏈接。

src/myProject/node_modules/myModule -> /usr/local/lib/node_modules/myModule

然后,就可以在你的項(xiàng)目中,加載該模塊了。

var myModule = require('myModule');

這樣一來,myModule的任何變化,都可以直接在myProject中調(diào)用。但是,同時(shí)也出現(xiàn)了風(fēng)險(xiǎn),任何在myProject目錄中對(duì)myModule的修改,都會(huì)反映到模塊的源碼中。

npm link命令有一個(gè)簡(jiǎn)寫形式,顯示連接模塊的本地目錄。

$ src/myProject$ npm link ../myModule

上面的命令等同于下面幾條命令。

$ src/myProject$ cd ../myModule
$ src/myModule$ npm link
$ src/myModule$ cd ../myProject
$ src/myProject$ npm link myModule

如果你的項(xiàng)目不再需要該模塊,可以在項(xiàng)目目錄內(nèi)使用npm unlink命令,刪除符號(hào)鏈接。

src/myProject$ npm unlink myModule

一般來說,npm公共模塊都安裝在系統(tǒng)目錄(比如/usr/local/lib/),普通用戶沒有寫入權(quán)限,需要用到sudo命令。這不是很方便,我們可以在沒有root的情況下,用好npm。

首先在主目錄下新建配置文件.npmrc,然后在該文件中將prefix變量定義到主目錄下面。

prefix = /home/yourUsername/npm

然后在主目錄下新建npm子目錄。

$ mkdir ~/npm

此后,全局安裝的模塊都會(huì)安裝在這個(gè)子目錄中,npm也會(huì)到~/npm/bin目錄去尋找命令。因此,npm link就不再需要 root權(quán)限了。

最后,將這個(gè)路徑在.bash_profile文件(或.bashrc文件)中加入PATH變量。

export PATH=~/npm/bin:$PATH

npm publish

在發(fā)布你的模塊之前,需要先設(shè)定個(gè)人信息。

$ npm set init.author.name “張三”
$ npm set init.author.email “zhangsan@email.com”
$ npm set init.author.url “http://your.url.com"

這些信息會(huì)存放在用戶主目錄的~/.npmrc文件,使得用戶不用每個(gè)項(xiàng)目都輸入。如果遇到某個(gè)模塊的作者信息,與全局設(shè)置不同,可以在項(xiàng)目目錄中,單獨(dú)設(shè)置一次上面這些命令。

然后,向npm系統(tǒng)申請(qǐng)用戶名。

$ npm adduser

運(yùn)行上面的命令之后,屏幕上會(huì)提示輸入用戶名,然后是輸入Email地址和密碼。

如果已經(jīng)注冊(cè)過,就使用下面的命令登錄。

$ npm login

最后,使用npm publish命令發(fā)布。

$ npm publish

npm version

npm version命令用來修改項(xiàng)目的版本號(hào)。當(dāng)你完成代碼修改,要發(fā)布新版本的時(shí)候,就用這個(gè)命令更新一下軟件的版本。

$ npm version <update_type> -m "<message>"

npm version命令的update_type參數(shù)有三個(gè)選項(xiàng):patch、minor、major。

  • npm version patch增加一位補(bǔ)丁號(hào)(比如 1.1.1 -> 1.1.2)
  • npm version minor增加一位小版本號(hào)(比如 1.1.1 -> 1.2.0)
  • npm version major增加一位大版本號(hào)(比如 1.1.1 -> 2.0.0)。

下面是一個(gè)例子。

$ npm version patch -m "Version %s - xxxxxx"

上面命令的%s表示新的版本號(hào)。

除了增加版本號(hào),npm version命令還會(huì)為這次修改,新增一個(gè)git commit記錄,以及一個(gè)新的git tag。

由于更新npm網(wǎng)站的唯一方法,就是發(fā)布一個(gè)新的版本。因此,除了第一次發(fā)布,這個(gè)命令與npm publish幾乎是配套的,先使用它,再使用npm publish。

參考鏈接

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)