NodeJS包管理工具——npm入門


如今每個語言體系中都有一個包管理工具,PHP的Composer,Ruby的gem,Python的pip,Java的Maven……當然還有Node.js的npm。有的人會奇怪為何要引入又一個新東西來讓我們已經夠辛苦的編程工作雪上加霜呢?其實不然,例如我們在做Java開發的時候,有的項目依賴數百個jar,開發人員在build之前總會碰到各種包版本,包找不到的問題,但包管理工具卻讓我們從這種依賴噩夢中解救出來。我們開發過程中的任何依賴,都可以通過這種工具自動從遠程的包倉庫中下載回來,並且保證是我們需要的版本,然我們可以專注於開發生產中。

唯一一個缺點,可能就是我東方大國和那些老外的主機距離有夠遠,經常無法通過官方鏡像下載,這種時候通常有三種辦法:一個是對包管理工具本身設置代理,第二個是直接全局VPN,第三個就是使用國內同步鏡像,當然前提是要有。
好了廢話不多說了,下面這篇文章要是出現在幾年前就好了,我當時頭一次接觸npm的時候也是有夠暈,希望這次的這篇文章能夠給初學者指明一個直路。

正文

Node.js讓開發者可以用JavaScript編寫服務端程序,它基於用C++編寫的JavaScript的V8引擎構建,所以它很快(你是否想說C更快?但要知道比起那些用Java編寫的中間件來說,C++已經很快了——譯者注)。起初,NodeJS主要是設計為做服務端程序開發的,但慢慢的,開發者們把它應用於構建本地自動化工具鏈。自此開放出了一片新的NodeJS生態環境(例如GruntGulp),讓新一代的前端開發者們逐漸形成了工程化的思想。
為了利用好這些工具(或者包),我們需要以一種良好的方式去安裝和管理它們(就像Windows的添加刪除程序一樣)。於是npm就誕生了,npm以你希望的方式安裝這些工具,並且提供了一個易用的接口組織這些工具。在我介紹之前,首先要在你的額系統中安裝Node.js。

安裝Node.js

去官網的下載頁可以獲取你需要的版本。Windows和Mac都有現成的安裝包。而對於Linux平台來說也准備了預編譯好的二進制文件和源代碼。另外,你也可以用對應Linux發行版的包管理工具來安裝。
在本文撰寫之時(2016年4月3日)官方最新版是v.5.10.0 stable。
下面讓我們看看如何查看Node的安裝路徑以及版本:

$ which node /usr/local/bin/node $ node --version v5.7.0

我們通過來嘗試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一起裝好了,無需額外安裝。

$ which npm /usr/local/bin/npm $ npm --version 3.6.0

用Node.js安裝模塊

npm可以在你的某個項目中單獨安裝模塊,也可以在你的電腦中全局安裝。在某個項目中單獨安裝的時候,npm會下載所有的文件到你項目中的一個叫做node_modules的文件夾內。這個文件夾的所有者是當前用戶(在Linux中,對文件夾的所有者權限敏感,其他用戶如果沒有授權是無法查看另一個用戶擁有的文件的,Windows中雖然也有這個概念,但通常我們個人電腦用戶都很單一,所以並不是很重視這個概念——譯者注)。全局模塊會被安裝到{prefix}/lib/node_modules/這個目錄下,目錄的擁有者是root用戶({prefix}通常是/usr/或者/usr/local/)。這意味着如果你要在某個Linux發行版下全局安裝模塊,需要用sudo命令,否則會引發權限錯誤。

更改全局模塊安裝路徑

首先讓我們看一下npm config這個命令會輸出什么

$ npm config list ; cli configs user-agent = "npm/3.6.0 node/v5.7.0 linux x64" ; node bin location = /usr/local/bin/node ; cwd = /home/sitepoint ; HOME = /home/sitepoint ; 'npm config ls -l' to show all defaults.

這里列出了npm的基本配置信息,重點是這里

$ npm config get prefix /usr/local

列出了全局安裝模塊的路徑。我們通過下面的命令可以在我們的用戶主目錄下新建一個文件夾,然后把全局模塊安裝路徑更改到這個目錄下。

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

這樣,我們就更改了全局模塊的安裝位置了。做了責怪操作以后,我們同時也會得到一個自動新建的.npmrc文件。

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

但對於有強迫症的開發者來說,這樣還不夠,我們的npm還停留在root目錄下呢。不要緊,我們可以用下面的命令重新安裝npm到我們的本地目錄中。

$ npm install npm --global /home/sitepoint/.node_modules_global/bin/npm -> /home/sitepoint/.node_modules_global/lib/node_modules/npm/bin/npm-cli.js /home/sitepoint/.node_modules_global/lib └── npm@3.7.5

好了,最后一步,我們把.node_modules_global/bin添加到環境變量$PATH中,我們輸入npm命令的時候,就不會去root目錄下尋找,而是在我們自己的主目錄下尋找了。

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

現在我們用which命令可以確認我們現在用的npm是來自哪個目錄的了。

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

ok,這樣依賴,我們就不需要再用sudo來進行全局安裝了。

在全局安裝模塊

第一個例子,我們來裝一個包,叫做UglifyJS。這是一個JS壓縮工具。我們用--global這個參數來告訴npm我們要進行全局安裝,這個參數也可以簡寫為-g

$ npm list --global ├─┬ npm@3.7.5  ├── abbrev@1.0.7  ├── ansi-regex@2.0.0  ├── ansicolors@0.3.2  ├── ansistyles@0.1.3 .................... └─┬ uglify-js@2.6.2 ├── async@0.2.10 ├── source-map@0.5.3 ├── uglify-to-browserify@1.0.2

大家可以看到,這個輸出相當復雜,我們在安裝其他包的時候,有可能會更慘不忍睹。我們可以用--depth=0來告訴控制台只輸出一個層級的信息。

$ npm list -g --depth=0 ├── npm@3.7.5 └── uglify-js@2.6.2

好了,接下來你就可以直接用uglifyjs這個命令在shell中壓縮文件了。

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

在自己的項目中安裝模塊

不帶任何參數,直接用npm install命令即可在單獨的項目目錄中安裝模塊了。新的包會安裝到項目文件夾下的一個叫做node_modules的目錄中。例如,下面我們在本地安裝一個叫做underscore模塊(Underscore 是一個 JavaScript 工具庫,它提供了一整套函數式編程的實用功能):

$ mkdir ~/project && cd ~/project $ npm install underscore /home/sitepoint/project └── underscore@1.8.3 $ ls node_modules $ ls node_modules underscore

在自己項目中列出安裝過的模塊

我們可以通過npm list來列出自己項目已經安裝過的模塊

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

這就表示,我們可以在另一個項目目錄中,安裝另一個版本的underscore模塊。

卸載模塊

還是以underscore為例,讓我們卸載后並檢查這個模塊是否還存在:

$ npm uninstall underscore - underscore@1.8.3 node_modules/underscore $ npm list /home/sitepoint/project └── (empty)

安裝特定版本的模塊

默認情況下,npm總會尋找最新版本的包來安裝,但我們仍然可以通過參數指定安裝特定版本的模塊:

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

更新模塊

如果我們以前安裝的某個包,有了新版本,例如修復bug,那我們需要一條命令能直接對這個包進行升級。

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

注:我們需要在package.json中標記underscore為依賴才能讓上面的命令生效。(參見下面的“管理依賴”一節)

搜索模塊

我們在Linux通常會使用mkdir這個命令,那么npm中是否有這樣一種包能達到一樣的效果呢。在這個場景下,我們就可能會需要搜索某個具有特定功能的模塊,那么我們可以用如下命令去搜索:

$ npm search mkdir npm WARN Building the local index for the first time, please be patient

我們發現,還真有一個,叫做mkdirp。那我們試試直接安裝它

$ npm install mkdirp /home/sitepoint/project └─┬ mkdirp@0.5.1 └── minimist@0.0.8

然后我們試試看是否真的是我們想要的包

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

運行結果如下

$ node. mkdir.js Directory created!

ok,還真成功了~

管理緩存

通常,我們在用npm安裝了一個模塊以后,npm會保留一份安裝包到本地的.npm目錄中,以加速下次安裝同樣的包的速度。例如在Linux發行版,這個目錄是~

$ ls ~/.npm _locks minimist mkdirp registry.npmjs.org underscore

但日積月累,這個目錄下一定會積攢很多文件,所以我們需要一個命令清理它。

$ npm cache clean

管理依賴

現在,我們已經裝過2個包了,但是這以后肯定會需要更多包,所以我們每次都手動安裝並非明智之舉,這種時候,我們經常在github項目中看到的package.json就派上用場了。我們可以通過這個文件來管理我們的包安裝。而這個文件可以用npm init命令創建。

$ npm init This utility will walk you through creating a package.json file. Press ^C at any time to quit. name: (project) demo version: (1.0.0) description: Demo of package.json entry point: (index.js) test command: git repository: keywords: author: Sitepoint license: (ISC)

然后在項目根目錄會生成這樣一個package.json文件。我們對這個文件添加我們的依賴項,並設置一些參數:

JavaScript
{ "name": "demo", "version": "1.0.0", "description": "Demo package.json", "main": "main.js", "dependencies": { "mkdirp": "^0.5.1", "underscore": "^1.8.3" }, "devDependencies": {}, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Sitepoint", "license": "ISC" } 

下面這個命令可以省略大段的輸入參數,直接創建一個配置文件:

$ npm init --yes

package.json中的name參數將會用你項目的文件夾名字來自動設定。
我們可以通過添加private:true這個配置項來阻止不小心發布了私有的倉庫,而且可以阻止在執行npm install的時候會產生的警告。讓我們創建一個目錄,然后試試用package.json來下載模塊。

$ mkdir ~/demo && cd ~/demo $ cp ~/project/package.json ~/demo $ npm install $ npm list demo@1.0.0 /home/sitepoint/demo ├─┬ mkdirp@0.5.1  └── minimist@0.0.8 └── underscore@1.8.3

又有新問題了,如果我們要手動安裝新包的時候(不試用package.json,直接在shell用npm install命令),如何保持這個文件也能同步修改呢?我們可以用--save參數。例如下面,我們用--save參數安裝一個叫做request的新包

$ npm install request --save $ npm list --depth=0 demo@1.0.0 /home/sitepoint/demo ├── mkdirp@0.5.1 ├── request@2.53.0 └── underscore@1.8.3

然后,我們的package.json文件就會被自動更新為

JavaScript
"dependencies": { "mkdirp": "^0.5.1", "request": "^2.53.0", "underscore": "^1.8.3" } 

可以看到對應的包已經被加入了package.json中了,這全部過程不需要我們修改文件。

##版本管理器##
有幾個工具可以讓我們在同一台機器上使用不同版本的Node.js。其中一個叫做n。另一個叫做nvm(Node Version Manager)。有一篇教程是專門講這個問題的,這里就不贅述了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM