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/
中的全域性包由user根目錄所擁有({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安裝在由user根目錄所有的位置。但是要注意我們已經在配置中改變了全域性包安裝的位置。我們需要再次安裝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檔案
除了main
和scripts
外,其他欄位應該是一目瞭然的。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 ll
或npm 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了嗎?如果沒有,現在是開始使用它的好時機。