【譯】一份關于npm的新手指南

Node.js使得在服務器端使用JavaScript編寫應用程序成為可能。它是基于V8Javascript運行時并且使用C++編寫的,所以它的速度很快。最初,它旨在作為應用程序的服務器環境,但是開發人員使用它創建工具來幫助他們進行本地任務自動化。從那時起,一個全新的基于Node的工具生態系統(如Grunt,Gulp和Webpack)徹底改變了前端開發的面貌。

為了在Node.js中使用這些工具(或者包),我們需要能夠以有效的方式安裝和管理它們。這就是我們即將要討論的:npm--Node的包管理器。它負責安裝你需要使用的包,并且提供一個有用的界面讓你與它們交互。

在本文中,我將介紹使用npm的基礎知識。我將向你演示如何在本地和全局模式下安裝包,以及刪除,更新和安裝某個版本的包。我還會告訴你如何使用package.json處理項目的依賴。如果你更喜歡看視頻,請注冊SitePoint Premium觀看我們的免費錄屏:什么是npm以及如何使用?

在開始使用npm之前,首先需要在電腦中安裝Node.js。

安裝Node.js

去Node.js 下載頁面獲取你需要的版本。可以獲得Windows和Mac環境的安裝包和預編譯的Linux二進制文件以及源代碼。對于Linux環境,你還可以通過包管理器來安裝Node,如這里所述

本教程我們將使用v6.10.3穩定版本。在編寫本文時,這是Node的當前長期支持(LTS)版本

提示: 你也可以考慮使用版本管理器來安裝Node。這將消除下面提出的權限問題。

我們來看一下Node的安裝位置以及版本。

$ which node
/usr/bin/node
$ node --version
v6.10.3

使用Node的REPL(交互式解釋器)檢查安裝是否成功。

$ node
> console.log('Node is running');
Node is running
> .help
.break Sometimes you get stuck, this gets you out
.clear Alias for .break
.exit  Exit the repl
.help  Show repl options
.load  Load JS from a file into the REPL session
.save  Save all evaluated commands in this REPL session to a file
> .exit

Node.js已經安裝成功,現在我們可以把注意力集中在npm上,npm已經集成在上述安裝的Node.js中。

$ which npm
/usr/bin/npm
$ npm --version
3.10.10

Node包模塊

npm可以以本地或全局模式安裝包。在本地模式下,將包安裝在父工作目錄中的node_modules文件夾中。該位置由當前用戶所擁有。安裝在{prefix}/lib/node_modules/中的全局包由根目錄所擁有({prefix}通常是/usr//usr/local)。這意味著你將不得不使用sudo全局安裝包,這可能會在解決第三方依賴時導致權限錯誤,也可能導致安全問題。下面讓我們更改一下:

更改全局包的位置

讓我們看看運行npm config list輸出了什么:

$ npm config list
; cli configs
user-agent = "npm/3.10.10 node/v6.10.3 linux x64"

; userconfig /home/sitepoint/.npmrc
prefix = "/home/sitepoint/.node_modules_global"

; node bin location = /usr/bin/nodejs
; cwd = /home/sitepoint
; HOME = /home/sitepoint
; "npm config ls -l" to show all defaults.

輸出給了我們有關npm的安裝信息。現在,重要的是獲取當前的全局位置。

$ npm config get prefix
/usr

為了在主目錄中安裝全局包,我們需要更改這個前綴。為此,你可以在主文件夾中創建一個新目錄。

$ cd ~ && mkdir .node_modules_global
$ npm config set prefix=$HOME/.node_modules_global

通過這個簡單的配置更改,我們將位置更改為全局Node包安裝的位置。這個更改同時會在我們的主目錄中創建了一個.npmrc文件。

$ npm config get prefix
/home/sitepoint/.node_modules_global
$ cat .npmrc
prefix=/home/sitepoint/.node_modules_global

我們仍然將npm安裝在由根目錄所有的位置。但是要注意我們已經在配置中改變了全局包安裝的位置。我們需要再次安裝npm,但是這一次是安裝在新用戶所在的位置。當然,安裝的將是npm的最新版本。

$ npm install npm --global
└─┬ npm@5.0.2
  ├── abbrev@1.1.0
  ├── ansi-regex@2.1.1
....
├── wrappy@1.0.2
└── write-file-atomic@2.1.0

最后,我們需要添加.node_modules_global/bin到$PATH環境變量中,以便可以從命令行運行全局包。為了做到這一點,你可以把下面這一行添加到.profile.bash_profile或者.bashrc文件中并重新啟動終端。

export PATH="$HOME/.node_modules_global/bin:$PATH"

現在我們可以找到npm的所在目錄.node_modules_global/bin并且使用合適的npm版本。

$ which npm
/home/sitepoint/.node_modules_global/bin/npm
$ npm --version
5.0.2

在全局模式下安裝包

目前我們只有一個安裝在全局的包-那就是npm包本身。下面我們來安裝UglifyJS包(一個JavaScript的壓縮工具)。我們使用--global標記,也可以縮寫為-g。

$ npm install uglify-js --global
/home/sitepoint/.node_modules_global/bin/uglifyjs -> /home/sitepoint/.node_modules_global/lib/node_modules/uglify-js/bin/uglifyjs
+ uglify-js@3.0.15
added 4 packages in 5.836s

從輸出可以看出,還安裝了其他包, 這些包都是UglifyJS包的依賴項。

列出全局安裝包

我們可以使用npm list命令列出全局包。

$ npm list --global
home/sitepoint/.node_modules_global/lib
├─┬ npm@5.0.2
│ ├── abbrev@1.1.0
│ ├── ansi-regex@2.1.1
│ ├── ansicolors@0.3.2
│ ├── ansistyles@0.1.3
....................
└─┬ uglify-js@3.0.15
  ├─┬ commander@2.9.0
  │ └── graceful-readlink@1.0.1
  └── source-map@0.5.6

然而,輸出十分冗長。我們可以使用--depth=0選項進行優化。

$ npm list -g --depth=0
/home/sitepoint/.node_modules_global/lib
├── npm@5.0.2
└── uglify-js@3.0.15

我們發現這要更友好 -- 只顯示我們安裝的包及其版本號。

我們可以在命令行中使用任何全局安裝包。例如:下面的命令展現了如何使用Uglify 包將example.js壓縮到example.min.js

$ uglifyjs example.js -o example.min.js

在本地模式下安裝包

當你在本地安裝包時,通常會使用package.json文件進行安裝。下面讓我們創建這樣的一個文件。

$ npm init
package name: (project)
version: (1.0.0)
description: Demo of package.json
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)

Enter接受默認值,然后鍵入yes確認。這樣將會在項目的根目錄下創建一個package.json文件。內容如下:

{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

提示:你可以使用npm init --y命令以更快的方式生成package.json文件

除了mainscripts外,其他字段應該是一目了然的。main字段是你程序的主入口,scripts字段允許你指定在包的生命周期中的不同時間運行的腳本命令。我們暫時不討論這些東西,但是如果你想了解更多相關信息,請參閱《npm中的package.json文檔》和《使用npm作為構建工具》。

現在讓我們來安裝underscore包。

$ npm install underscore
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN project@1.0.0 No description
npm WARN project@1.0.0 No repository field.

+ underscore@1.8.3
added 1 package in 0.344s

注意這里創建了一個文件,我們稍后會講到它。

打開package.json文件我們會看到dependencies字段已經添加到了文件中:

{
  ...
  "dependencies": {
    "underscore": "^1.8.3"
  }
}

使用package.json管理依賴

如你所見,underscore v1.8.3安裝到了我們的項目中。版本號前面的(^)符號表示安裝時,npm將安裝最高版本的包,npm還可以找到主版本可以匹配的唯一位置(除非存在package-lock.json文件)。在我們的例子中,這是V2.0.0版本以下的所有版本。版本控制依賴(major.minor.patch)的這種方法被稱為語義化版本控制。你可以在《語義化版本控制:為什么你應該使用它?》文章中了解更多相關知識。

還要注意,underscore被保存為dependencies字段的屬性。這是最新版本npm的默認設置,用于運行應用程序所需的包(如underscore)。也可以通過指定--save-dev標志將包保存為devDependency。devDependencies是用于開發目的的包,例如運行測試或解析代碼。

你也可以給package.json文件添加private: true以防止意外發布私有倉庫并且阻止所有運行npm install時生成的警告。

其實使用package.json指定項目依賴的最大好處是可移植性。例如,當你克隆別人的代碼時,你只需要在根目錄運行npm i即可,然后npm將解析并獲取所有運行該應用程序必需的包。稍后我們再來看這個。

在結束此部分內容之前,我們快速檢查一下underscore是否正在工作。在項目根目錄下創建名為test.js的文件并寫入下列內容:

const _ = require('underscore');
console.log(_.range(5));

使用node test.js運行文件,你應該看到[0, 1, 2, 3, 4]輸出到了屏幕。

卸載本地安裝包

npm是一個包管理器,所以它肯定可以卸載一個包。我們假設當前的underscore包導致了兼容性問題。我們可以卸載這個包并安裝舊版本,如下所示:

$ npm uninstall underscore
removed 2 packages in 0.107s
$ npm list
project@1.0.0 /home/sitepoint/project
└── (empty)

安裝特定版本的包

我們通過使用@符號加一個版本號來安裝特定版本的underscore包。

$ npm install underscore@1.8.2
+ underscore@1.8.2
added 1 package in 1.574s

$ npm list
project@1.0.0 /home/sitepoint/project
└── underscore@1.8.2

更新包

讓我們檢查一下underscore包是否存在新版本:

$ npm outdated
Package     Current  Wanted  Latest  Location
underscore    1.8.2   1.8.3   1.8.3  project

Current列告訴我們當前安裝的版本。Latest列告訴我們包的最新版本。 Wanted列告訴我們在不破壞現有的代碼的前提下可以升級到的最新版本的包。

還記得之前的package-lock.json文件嗎?它是在npm v5中引入的,目的是確保安裝在計算機上的所有項目的依賴保持不變。當npm修改node_modules文件夾或package.json文件時它會自動生成。

如果你喜歡,你可以繼續嘗試。刪除node_modules文件夾,然后重新運行npm i。最新版本的npm將安裝underscore v1.8.2(因為這是package-lock.json文件中指定的)。根據語義化版本控制的規范,v1 .8.3將向下兼容早期版本。在過去,不一致的包版本對開發人員來說很頭痛的事情。這個問題通常通過使用必須手動創建的npm-shrinkwrap.json文件來解決。

現在,我們假設最新版本的underscore修復了我們之前提到的兼容性錯誤,我們希望將包更新為該版本。

$ npm update underscore
+ underscore@1.8.3
updated 1 package in 0.236s

$ npm list
project@1.0.0 /home/sitepoint/project
└── underscore@1.8.3

提示:為了使上述命令工作正常,underscore必須被列為package.json的依賴項。如果我們有更多的過時模塊,我們也可以執行npm update

搜索包

在本教程中我們已經多次使用了mkdir命令。是否存在一個包做相同的事情呢?讓我們使用npm search命令看一下。

$ npm search mkdir
NAME      | DESCRIPTION          | AUTHOR          | DATE       | VERSION
mkdir     | Directory crea…      | =joehewitt      | 2012-04-17 | 0.0.2
fs-extra  | fs-extra conta…      | =jprichardson…  | 2017-05-04 | 3.0.1
mkdirp    | Recursively mkdir,…  | =substack       | 2015-05-14 | 0.5.1
...

這里有一個mkdirp包,我們來安裝它。

$ npm install mkdirp
+ mkdirp@0.5.1
added 2 packages in 3.357s

創建mkdir.js文件并復制粘貼此代碼:

const mkdirp = require('mkdirp');
mkdirp('foo', function (err) {
  if (err) console.error(err)
  else console.log('Directory created!')
});

從終端運行這個文件:

$ node mkdir.js
Directory created!

重新安裝項目依賴

我們先安裝一個包:

$ npm install request
+ request@2.81.0
added 54 packages in 15.92s

檢查package.json文件。

"dependencies": {
  "mkdirp": "^0.5.1",
  "request": "^2.81.0",
  "underscore": "^1.8.2"
},

注意依賴項列表會自動更新。在以前的npm版本中,你將不得不執行npm install request --save以保存package.json中的依賴關系。如果你想安裝一個包而不在package.json中保存它,只需使用--no-save參數。

假設你將項目源代碼克隆到了另一臺計算機,現在需要安裝依賴項。我們先刪除node_modules文件夾然后執行npm install

$ rm -R node-modules
$ npm list
project@1.0.0 /home/sitepoint/project
├── UNMET DEPENDENCY mkdirp@^0.5.1
├── UNMET DEPENDENCY request@^2.81.0
└── UNMET DEPENDENCY underscore@^1.8.2

npm ERR! missing: mkdirp@^0.5.1, required by project@1.0.0
npm ERR! missing: request@^2.81.0, required by project@1.0.0
npm ERR! missing: underscore@^1.8.2, required by project@1.0.0

$ npm install
added 57 packages in 1.595s

注意觀察node_modules文件夾,你會發現它已經被重新創建。像這樣,你就可以輕松地與他人共享你的代碼,而不會導致你的項目和源依賴倉庫膨脹。

管理緩存

當npm安裝一個包時,其實它保存了一個副本。所以下次你安裝這個包的時候就不需要再連接網絡。這些副本緩存在你的主路徑下的.npm目錄中。

$ ls ~/.npm
anonymous-cli-metrics.json  _cacache  _locks  npm  registry.npmjs.org

這個目錄會隨著時間的推移而變得亂七八糟,所以有時候要清理它。

$ npm cache clean

如果你要清理系統上的多個Node項目,還可以從工作區清除所有node_module文件夾。

find . -name "node_modules" -type d -exec rm -rf '{}' +

別名

可能你已經注意到,運行npm命令有多種方式。以下是一些常用的npm別名的簡要列表:

  • npm i <package> - 安裝本地包
  • npm i -g <package>- 安裝全局包
  • npm un <package> - 卸載本地包
  • npm up - npm更新包
  • npm t - 運行測試
  • npm ls - 列出已安裝的模塊
  • npm llnpm la- 在列出模塊時打印附加包信息

你也可以一次安裝多個軟件包:

$ npm i express momemt lodash mongoose body-parser webpack

如果想要學習所有常見的npm命令,執行npm help獲取完整的命令列表。你也可以在我的《10個技巧,使你成為npm忍者》文章中學到更多相關知識。

版本管理器

有幾種有用的工具可以讓你在同一臺機器上管理多個版本的Node.js。其中一個就是n,另一個是nvm(Node 版本管理器)。如果這是你感興趣的內容,可以看看我們的教程:《使用nvm安裝多個版本的Node.js》。

總結

在本教程中,我介紹了使用npm的基礎知識,演示了如何從下載頁面安裝Node.js,如何更改全局包的位置(所以我們可以避免使用sudo)以及如何在本地和全局模式下安裝包。我還介紹了刪除,更新和安裝某個版本的包,以及管理項目的依賴。如果你想了解有關最新版本中的新功能的更多信息,可以訪問npm Github發行頁面。

隨著版本5的發行,npm正在向前端開發的世界邁進。根據其首席運營官的介紹,npm用戶基礎正在發生變化,其中大多數開發者使用它們并沒有使用它來編寫Node。相反,它正在成為人們在前端開發中整合JavaScript的工具(你可以使用它來安裝任何東西)并且它正在成為編寫現代JavaScript的組成部分。你在你的項目中使用npm了嗎?如果沒有,現在是開始使用它的好時機。

原文地址:https://www.sitepoint.com/beginners-guide-node-package-manager/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容