1. 程式人生 > >npm源管理器教程

npm源管理器教程

npm源管理器教程

npm簡介

npm 是 Node.js 官方提供的包管理工具,他已經成了 Node.js 包的標準釋出平臺,用於 Node.js 包的釋出、傳播、依賴控制。npm 提供了命令列工具,使你可以方便地下載、安裝、升級、刪除包,也可以讓你作為開發者釋出並維護包。。

npm安裝

npm 不需要單獨安裝。在安裝 Node 的時候,會連帶一起安裝 npm 。但是,Node 附帶的 npm 可能不是最新版本,最後用下面的命令,更新到最新版本。

# sudo npm install npm -g

選裝cnpm

因為npm安裝外掛是從國外伺服器下載,受網路影響大,可能出現異常,所以我們樂於分享的淘寶團隊幹了這事。來自官網:“這是一個完整 npmjs.org 映象,你可以用此代替官方版本(只讀),同步頻率目前為 10分鐘 一次以保證儘量與官方服務同步。”

# sudo npm install cnpm -g --registry=https://registry.npm.taobao.org

cnpm跟npm用法完全一致,只是在執行命令時將npm改為cnpm。

選裝nrm

npm包有很多的映象源,有的源有的時候訪問失敗,有的源可能沒有最新的包等等,所以有時需要切換npm的源,nrm包就是解決快速切換問題的。
nrm可以幫助您在不同的npm源地址之間輕鬆快速地切換。

# sudo npm install -g nrm

檢視是否安裝成功:nrm --version

# nrm --version
1.0.2

nrm內建瞭如下源:

URL 主頁
npm https://registry.npmjs.org/ https://www.npmjs.com/
cnpm http://r.cnpmjs.org/ https://cnpmjs.org/
taobao https://registry.npm.taobao.org/ https://npm.taobao.org/
nj https://registry.nodejitsu.com/ https://www.nodejitsu.com/
rednpm http://registry.mirror.cqupt.edu.cn/ http://npm.mirror.cqupt.edu.cn/
npmMirror https://skimdb.npmjs.com/registry/ https://skimdb.npmjs.com/
edunpm http://registry.enpmjs.org/ http://www.enpmjs.org/

經過本人實測,nj、rednpm、edunpm 源訪問失敗(2019-1-14)。

nrm使用

列出可選擇的源:

# nrm ls
  npm ---- https://registry.npmjs.org/
  cnpm --- http://r.cnpmjs.org/
* taobao - https://registry.npm.taobao.org/
  nj ----- https://registry.nodejitsu.com/
  rednpm - http://registry.mirror.cqupt.edu.cn/
  npmMirror  https://skimdb.npmjs.com/registry/
  edunpm - http://registry.enpmjs.org/

注: 前面帶 * 號的表示正在使用的源

切換使用的源:

# nrm use npm
Registry has been set to: https://registry.npmjs.org/

新增一個源:

如果你想新增一個源,終端執行命令nrm add [home],reigstry為源名,url為源的路徑, home為源的主頁(可不寫)。

# nrm add company http://npm.company.com/  
add registry company success

URL最後的/也可以不帶,下面兩個URL都是可以的:
http://npm.company.com/
http://npm.company.com
[home]引數用於nrm home命令,用來檢視源的主頁。

刪除一個源:

想要刪除一個源,終端執行命令nrm del ,reigstry為源名.

# nrm del company
delete registry company success

注:nrm del 命令不能刪除nrm自己內建的源。

測試源速度:

測試一個源的響應時間:nrm test npm

# nrm test npm
npm ---- 2050ms

測試所有源的速度:nrm test

# nrm test
  npm ---- 563ms
  cnpm --- 299ms
* taobao - 510ms
  nj ----- Fetch Error
  rednpm - Fetch Error
  npmMirror  67917ms
  edunpm - Fetch Error

訪問源的主頁:

如果你想訪問源的主頁,可在終端輸入下面命令:

# nrm home taobao

此命令會在瀏覽器中開啟淘寶源的主頁:https://npm.taobao.org/

如果要檢視自己新增的源的主頁,那麼在新增源的時候就要把主頁帶上:
~ nrm add company http://npm.company.com/ http://npm.company.com/

如果新增源的時候沒有寫home資訊,那麼nrm home命令不會有效果。

使用npm設定源:

預設的npm倉庫地址是:https://registry.npmjs.org,但是因為牆的原因,所以國內使用的時候需要更改映象地址:
淘寶的映象地址:
https://registry.npm.taobao.org
國內的映象地址:
https://registry.cnpmjs.org
更改映象地址的方法(以淘寶為例):

設定一個淘寶的映象源:

# npm config set registry https://registry.npm.taobao.org/ --global

設定node原始碼的源:

# npm config set disturl https://npm.taobao.org/dist --global

設定成功後終端不會有任何輸出。後面的global是設定全域性映象。

檢視當前使用的源:

# npm config get registry -g
https://registry.npm.taobao.org/
# npm config get disturl -g
https://npm.taobao.org/dist

後面加上-g查詢全域性的,不加檢視當前使用者。
設定完成後,會儲存在系統檔案,使用npm config ls可以檢視所有配置檔案地址以及內容。然後可以直接在其檔案中直接修改。

使用特定源安裝包

全部使用特定源安裝:

# npm install --registry=https://registry.npm.taobao.org

安裝一個包使用特定源:

# npm install logo --registry=https://registry.npm.taobao.org

npm使用

npm init

npm init 用來初始化生成一個新的 package.json 檔案。它會向用戶提問一系列問題,如果你覺得不用修改預設配置,一路回車就可以了。
如果使用了 -f(代表force)、-y(代表yes),則跳過提問階段,直接生成一個新的 package.json 檔案。

# npm init -y

npm set

npm set 用來設定環境變數

# npm set init-author-name 'Your name'
# npm set init-author-email 'Your email'
# npm set init-author-url 'http://yourdomain.com'
# npm set init-license 'MIT'

上面命令等於為 npm init 設定了預設值,以後執行 npm init 的時候,package.json 的作者姓名、郵件、主頁、許可證欄位就會自動寫入預設的值。這些資訊會存放在使用者主目錄的 ~/.npmrc檔案,使得使用者不用每個專案都輸入。如果某個專案有不同的設定,可以針對該專案執行 npm config。

npm info

npm info 命令可以檢視每個模組的具體資訊。比如,檢視 underscore 模組的資訊。

# npm info underscore

上面命令返回一個 JavaScript 物件,包含了 underscore 模組的詳細資訊。這個物件的每個成員,都可以直接從 info 命令查詢。

# npm info underscore description
# npm info underscore homepage
# npm info underscore version

npm search

npm search 命令用於搜尋 npm 倉庫,它後面可以跟字串,也可以跟正則表示式。

# npm search express

npm list

npm list 命令以樹形結構列出當前專案安裝的所有模組,以及它們依賴的模組。

# npm list 

加上 global 引數,會列出全域性安裝的模組

# npm list -global

列出單個模組

#  npm list underscore

npm install

使用 npm 安裝包的命令格式為:
npm [install/i] [package_name]

本地模式和全域性模式:
npm 在預設情況下會從 http://npmjs.org 搜尋或下載包,將包安裝到當前目錄的 node_modules 子目錄下。

如果你熟悉 Ruby的 gem 或者 Python 的 pip,你會發現npm與它們的行為不同,gem 或 pip 總是以全域性模式安裝,使包可以供所有的程式使用,而 npm 預設會把包安裝到當前目錄下。這反映了npm 不同的設計哲學。如果把包安裝到全域性,可以提供程式的重複利用程度,避免同樣的內容的多分副本,但壞處是難以處理不同的版本依賴。如果把包安裝到當前目錄,或者說本地,則不會有不同程式依賴不同版本的包的衝突問題,同時還減輕了包作者的 API 相容性壓力,但缺陷則是同一個包可能會被安裝許多次。

我們在使用 supervisor 的時候使用了 npm install -g supervisor 命令,就是以全域性模式安裝 supervisor 。

這裡注意一點的就是,supervisor 必須安裝到全域性,如果你不安裝到全域性,錯誤命令會提示你安裝到全域性。如果不想安裝到預設的全域性,也可以自己修改全域性路徑到當前路徑 npm config set prefix “路徑” 安裝完以後就可以用 supervisor 來啟動服務了。

supervisor 可以幫助你實現這個功能,它會監視你對程式碼的驅動,並自動重啟 Node.js

一般來說,全域性安裝只適用於工具模組,比如 eslint 和 gulp 。關於使用全域性模式,多數時候並不是因為許多程式都有可能用到了它,為了減少多重副本而使用全域性模式,而是因為本地模式不會註冊 PATH 環境變數。

“本地安裝”指的是將一個模組下載到當前專案的 node_modules 子目錄,然後只有在專案目錄之中,才能呼叫這個模組。

本地模式和全域性模式的特點如下:

模式 可通過 require 使用 註冊 PATH
本地模式
全域性模式

本地安裝

# npm install <package name>

全域性安裝

# sudo npm install -g <package name>

npm install 也支援直接輸入 Github 程式碼庫地址。

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

安裝之前,npm install 會先檢查,node_modules 目錄之中是否已經存在指定模組。如果存在,就不再重新安裝了,即使遠端倉庫已經有了一個新版本,也是如此。

如果你希望,一個模組不管是否安裝過, npm 都要強制重新安裝,可以使用 -f 或 --force 引數。

# npm install <packageName> --force

安裝不同版本:

install 命令總是安裝模組的最新版本,如果要安裝模組的特定版本,可以在模組名後面加上 @ 和版本號。

# npm install [email protected]
# npm install [email protected]
# npm install [email protected]">=0.1.0 <0.2.0"

install 命令可以使用不同引數,指定所安裝的模組屬於哪一種性質的依賴關係,即出現在 packages.json 檔案的哪一項中。

–save-dev 是作為開發依賴儲存到 packsge.json 中的 devDependencies 中,即在開發環境中用到的依賴,如 webpack、babel 等用於開發打包的依賴,只是在執行打包時才會用到,開發的程式碼中並不包含這些依賴
–save 安裝的則是需要在你開發的程式碼中用到的依賴,如 vue,你需要 import Vue from vue。

# npm install sax --save
# npm install node-tap --save-dev

dependencies 依賴

這個可以說是我們 npm 核心一項內容,依賴管理,這個物件裡面的內容就是我們這個專案所依賴的 js 模組包。下面這段程式碼表示我們依賴了 markdown-it 這個包,版本是 ^8.1.0 ,代表最小依賴版本是 8.1.0 ,如果這個包有更新,那麼當我們使用 npm install 命令的時候,npm 會幫我們下載最新的包。當別人引用我們這個包的時候,包內的依賴包也會被下載下來。

"dependencies": {
    "markdown-it": "^8.1.0"
}

devDependencies 開發依賴

在我們開發的時候會用到的一些包,只是在開發環境中需要用到,但是在別人引用我們包的時候,不會用到這些內容,放在 devDependencies 的包,在別人引用的時候不會被 npm 下載。

"devDependencies": {
    "autoprefixer": "^6.4.0",0",
    "babel-preset-es2015": "^6.0.0",
    "babel-preset-stage-2": "^6.0.0",
    "babel-register": "^6.0.0",
    "webpack": "^1.13.2",
    "webpack-dev-middleware": "^1.8.3",
    "webpack-hot-middleware": "^2.12.2",
    "webpack-merge": "^0.14.1",
    "highlightjs": "^9.8.0"
}

當你有了一個完整的 package.json 檔案的時候,就可以讓人一眼看出來,這個模組的基本資訊,和這個模組所需要依賴的包。我們可以通過 npm install 就可以很方便的下載好這個模組所需要的包。

npm install 預設會安裝 dependencies 欄位和 devDependencies 欄位中的所有模組,如果使用 --production 引數,可以只安裝 dependencies 欄位的模組。

# npm install --production

一旦安裝了某個模組,就可以在程式碼中用 require 命令載入這個模組。

var backbone = require('backbone')
console.log(backbone.VERSION)

npm run

npm 不僅可以用於模組管理,還可以用於執行指令碼。package.json 檔案有一個 scripts 欄位,可以用於指定指令碼命令,供 npm 直接呼叫。
package.json

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

scripts 指令碼

顧名思義,就是一些指令碼程式碼,可以通過 npm run script-key 來呼叫,例如在這個 package.json 的資料夾下使用 npm run dev 就相當於運行了 node build/dev-server.js 這一段程式碼。使用 scripts 的目的就是為了把一些要執行的程式碼合併到一起,使用 npm run 來快速的執行,方便省事。
npm run 是 npm run-script 的縮寫,一般都使用前者,但是後者可以更好的反應這個命令的本質。

// 指令碼
"scripts": {
    "dev": "node build/dev-server.js",
    "build": "node build/build.js",
    "docs": "node build/docs.js",
    "build-docs": "npm run docs & git checkout gh-pages & xcopy /sy dist\\* . & git add . & git commit -m 'auto-pages' & git push & git checkout master",
    "build-publish": "rmdir /S /Q lib & npm run build &git add . & git commit -m auto-build & npm version patch & npm publish & git push",
    "lint": "eslint --ext .js,.vue src"
}

npm run 如果不加任何引數,直接執行,會列出 package.json 裡面所有可以執行的指令碼命令。
npm 內建了兩個命令簡寫, npm test 等同於執行 npm run test,npm start 等同於執行 npm run start。

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

上面的寫法是先執行 npm run build-js ,然後再執行 npm run build-css ,兩個命令中間用 && 連線。如果希望兩個命令同時平行執行,它們中間可以用 & 連線。

寫在 scripts 屬性中的命令,也可以在 node_modules/.bin 目錄中直接寫成 bash 指令碼。下面是一個 bash 指令碼。

#!/bin/bash

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

假定上面的指令碼檔名為 build.sh ,並且許可權為可執行,就可以在 scripts 屬性中引用該檔案。

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

pre- 和 post- 指令碼

npm run 為每條命令提供了 pre- 和 post- 兩個鉤子(hook)。以 npm run lint 為例,執行這條命令之前,npm 會先檢視有沒有定義 prelint 和 postlint 兩個鉤子,如果有的話,就會先執行 npm run prelint,然後執行 npm run lint,最後執行 npm run postlint。

{
  "name": "myproject",
  "devDependencies": {
    "eslint": "latest"
    "karma": "latest"
  },
  "scripts": {
    "lint": "eslint --cache --ext .js --ext .jsx src",
    "test": "karma start --log-leve=error karma.config.js --single-run=true",
    "pretest": "npm run lint",
    "posttest": "echo 'Finished running tests'"
  }
}

上面程式碼是一個 package.json 檔案的例子。如果執行 npm test,會按下面的順序執行相應的命令。

  1. pretest
  2. test
  3. posttest

如果執行過程出錯,就不會執行排在後面的指令碼,即如果 prelint 指令碼執行出錯,就不會接著執行 lint 和 postlint 指令碼。

npm bin

npm bin 命令顯示相對於當前目錄的,Node 模組的可執行指令碼所在的目錄(即 .bin 目錄)。

# 專案根目錄下執行
# npm bin
./node_modules/.bin

建立全域性連結

npm 提供了一個有趣的命令 npm link,它的功能是在本地包和全域性包之間建立符號連結。我們說過使用全域性模式安裝的包不能直接通過 require 使用。但通過 npm link 命令可以打破這一限制。舉個例子,我們已經通過 npm install -g express 安裝了 express,這時在工程的目錄下執行命令:

# npm link express ./node_modules/express -> /user/local/lib/node_modules/express

我們可以在 node_modules 子目錄中發現一個指向安裝到全域性的包的符號連結。通過這種方法,我們就可以把全域性包當做本地包來使用了。

除了將全域性的包連結到本地以外,使用 npm link 命令還可以將本地的包連結到全域性。使用方法是在包目錄(package.json 所在目錄)中執行 npm link 命令。如果我們要開發一個包,利用這種方法可以非常方便地在不同的工程間進行測試。

建立包

包是在模組基礎上更深一步的抽象,Node.js 的包類似於 C/C++ 的函式庫或者 Java、.Net 的類庫。它將某個獨立的功能封裝起來,用於釋出、更新、依賴管理和版本控制。Node.js 根據 CommonJS 規範實現了包機制,開發了 npm 來解決包的釋出和獲取需求。
Node.js 的包是一個目錄,其中包含了一個 JSON 格式的包說明檔案 package.json。嚴格符合 CommonJS 規範的包應該具備以下特徵:
。package.json 必須在包的頂層目錄下;
。二進位制檔案應該在 bin 目錄下;
。JavaScript 程式碼應該在 lib 目錄下;
。文件應該在 doc 目錄下;
。單元測試應該在 test 目錄下。

Node.js 對包的要求並沒有這麼嚴格,只要頂層目錄下有 package.json,並符合一些規範即可。當然為了提高相容性,我們還是建議你在製作包的時候,嚴格遵守 CommonJS 規範。

我們也可以把資料夾封裝為一個模組,即所謂的包。包通常是一些模組的集合,在模組的基礎上提供了更高層的抽象,相當於提供了一些固定介面的函式庫。通過定製 package.json,我們可以建立更復雜,更完善,更符合規範的包用於釋出。

Node.js 在呼叫某個包時,會首先檢查包中 packgage.json 檔案的 main 欄位,將其作為包的介面模組,如果 package.json 或 main 欄位不存在,會嘗試尋找 index.js 或 index.node 作為包的介面。

package.json 是 CommonJS 規定的用來描述包的檔案,完全符合規範的 package.json 檔案應該含有以下欄位:

name: 包的名字,必須是唯一的,由小寫英文字母、數字和下劃線組成,不能包含空格。
description: 包的簡要說明。
version: 符合語義化版本識別規範的版本字串。
keywords: 關鍵字陣列,通常用於搜尋。
maintainers: 維護者陣列,每個元素要包含 name 、email(可選)、web(可選)欄位。
contributors: 貢獻者陣列,格式與 maintainers 相同。包的作者應該是貢獻者陣列的第一個元素。
bugs: 提交 bug 的地址,可以是網址或者電子郵件地址。
licenses: 許可證陣列,每個元素要包含 type(許可證的名稱)和 url(連結到許可證文字的地址)欄位。
repositories: 倉庫託管地址陣列,每個元素要包含 type(倉庫的型別,如 git)、URL(倉庫的地址)和 path(相對於倉庫的路徑,可選)欄位。
dependencies: 包的依賴,一個關聯陣列,由包名稱和版本號組成。

包的釋出

通過使用 npm init 可以根據互動式回答產生一個符合標準的 package.json。建立一個 index.js 作為包的介面,一個簡單的包就製作完成了。
在釋出前,我們還需要獲得一個賬號用於今後維護自己的包,使用 npm adduser 根據提示完成賬號的建立。

完成後可以使用 npm whoami 檢測是否已經取得了賬號。

接下來,在 package.json 所在目錄下執行 npm publish,稍等片刻就可以完成釋出了,開啟瀏覽器,訪問 http://search.npmjs.org/ 就可以找到自己剛剛釋出的包了。現在我們可以在世界的任意一臺計算機上使用 npm install neveryumodule 命令來安裝它。

如果你的包將來有更新,只需要在 package.json 檔案中修改 version 欄位,然後重新使用 npm publish 命令就行了。
如果你對已釋出的包不滿意,可以使用 npm unpublish 命令來取消釋出。

需要說明的是:json 檔案不能有註釋

參考連結

【1】http://javascript.ruanyifeng.com/nodejs/npm.html
【2】https://www.jianshu.com/p/f581cf9360a2
【3】https://segmentfault.com/a/1190000017419993
【4】https://segmentfault.com/q/1010000009821306