現代前端開發已經離不開Node了。你們都知道在安裝Node時會附贈一個命令行工具Node Package Manager,即npm。或許你已經照着教程輸入過好多遍」npm install xxx」,而且你發現npm的命令林林總總幾十條,package.json的配置項使人眼花繚亂,但不知你有沒有認真想過,咱們爲何須要npm?若是沒有它,世界會怎樣?
個人理解,npm所作的一切都是爲了解決軟件工程界一個一直以來的追求:代碼複用。抓住這個核心,也就抓住了正確理解和使用npm的鑰匙。
爲何要複用代碼呢?由於基於已有的成熟代碼快速開發新的應用,能夠極大地提升開發效率,正所謂「站在巨人肩膀上」「不要重複造輪子」。
So,在Node環境下要複用JS代碼,咱們有哪些方案呢? php
複製粘貼代碼的思路很直接,但現在還在的這樣搞的同窗應該是從原始社會穿越來的吧。。這個方案最大的缺點倒還不是代碼冗餘,而是一旦所複製的原始代碼發生了變化,那就必須手動修改每一處複本,在稍有規模的項目里根本不可行。 css
Node實現了一個模塊系統CommonJS,實在是JSer的一大福音。藉助它,咱們沒必要再複製粘貼代碼了:假如一個做者開發了一個名爲lib1的庫,他只需代碼寫在一個名叫lib1.js的文件裏,用module.export語句導出;而使用者只需把lib1.js下載到本身工程目錄,require一下即可直接用啦!(此時lib1也被稱爲一個「依賴」)
但這裏仍然存在兩個大問題:
一,若是lib1.js自己也複用了別的代碼,好比lib2.js、lib3.js...那你在下載lib1.js的時候,必須手動把它所依賴的這些模塊文件也一併下載;可要是lib2.js還依賴lib5.js、lib6.js....呢?一棵龐大的、深不見底的依賴樹很難手工管理。
2、lib1.js的做者修復了幾個bug,但沒有一個機制能讓他通知你升級舊的模塊文件。
做爲一名職業素養良好的程序員,看到這些問題的第一反應是否是「寫個腳本」?哈哈,不用麻煩了,由於已經有人替咱們寫好了,這個腳本工具就是npm。 html
有了上面「自力更生」的原始體驗,再看看npm提供的依賴安裝、卸載、升級、發佈等一條龍服務,是否是很爽?
Npm制定了一個包規範,所謂規範就是一些格式和約定,好比約定從package.json文件裏讀取這個包的全部信息,包括它的名字、版本號、它依賴於哪些別的包等;又好比約定node_modules目錄專門用來存放第三方依賴,Node爲此提供的支持是內置的require方法默認會到這個目錄下去檢索模塊,而無需手動指定路徑。有了這些規範,一個包的開發、依賴安裝、發佈等都步驟都標準化了,省心省力。
能夠說,JavaScript從一門「玩具」語言,到現在能夠勝任大型項目開發,模塊化和npm是其進化路上的重要一步。前端
後記
你們都知道前端有「三板斧」,但剛纔我一直在談JS,徹底沒提到另外兩板斧。這是由於npm只是「Node模塊管理器」,Node上又沒有HTML和CSS,npm天然管不到。那麼除了能夠直接支持Node端的開發之外,npm又如何爲瀏覽器端開發提供支持呢?
答案是:npm生態圈提供了不少強大的前端開發工具,好比Webpack、Babel、ESLint等。特別是Webpack、Browserify、rollup這類構建工具,能夠接手瀏覽器端的依賴管理重任,以及不少其餘的附加功能。這些內容,且待下回分解。。
前端十萬個爲何(之一):咱們爲何須要npm?
標籤:重要 col 以及 檢索 xxx 存在 你在 語句 16px
原文:http://www.cnblogs.com/leegen...vue
什麼是 NPM 爲何要使用 NPM 如何使用 NPM 安裝 使用 npm init npm set npm info npm search npm list npm install 本地模式和全局模式 安裝不一樣版本 dependencies 依賴 devDependencies 開發依賴 npm run scripts 腳本 pre- 和 post- 腳本 npm bin 建立全局連接 建立包 包的發佈 參考連接 個人經常使用命令
什麼是 NPM npm 之於 Node.js ,就像 pip 之於 Python, gem 之於 Ruby, pear 之於 PHP 。
npm 是 Node.js 官方提供的包管理工具,他已經成了 Node.js 包的標準發佈平臺,用於 Node.js 包的發佈、傳播、依賴控制。npm 提供了命令行工具,使你能夠方便地下載、安裝、升級、刪除包,也可讓你做爲開發者發佈並維護包。
爲何要使用 NPM npm 是隨同 Node.js 一塊兒安裝的包管理工具,能解決 Node.js 代碼部署上的不少問題,常見的場景有如下幾種:
容許用戶從 npm 服務器下載別人編寫的第三方包到本地使用。 容許用戶從 npm 服務器下載並安裝別人編寫的命令行程序到本地使用。 容許用戶將本身編寫的包或命令行程序上傳到 npm 服務器供別人使用。
npm 的背後,是基於 couchdb 的一個數據庫,詳細記錄了每一個包的信息,包括做者、版本、依賴、受權信息等。它的一個很重要的做用就是:將開發者從繁瑣的包管理工做(版本、依賴等)中解放出來,更加專一於功能的開發。
如何使用 NPM 安裝 npm 不須要單獨安裝。在安裝 Node 的時候,會連帶一塊兒安裝 npm 。可是,Node 附帶的 npm 可能不是最新版本,最後用下面的命令,更新到最新版本。
1node
$ sudo npm install npm@latest -g
若是是 Window 系統使用如下命令便可:
1webpack
npm install npm -g
也就是使用 npm 安裝本身。之因此能夠這樣,是由於 npm 自己與 Node 的其餘模塊沒有區別。 而後,運行下面的命令,查看各類信息。
1
2
3
4
5
6
7
8
9
10
11git
# 查看 npm 命令列表
$ npm help
# 查看各個命令的簡單用法
$ npm -l
# 查看 npm 的版本
$ npm -v
# 查看 npm 的配置
$ npm config list -l
使用 npm init npm init 用來初始化生成一個新的 package.json 文件。它會向用戶提問一系列問題,若是你以爲不用修改默認配置,一路回車就能夠了。
若是使用了 -f(表明force)、-y(表明yes),則跳過提問階段,直接生成一個新的 package.json 文件。
?
1程序員
$ npm init -y
npm set npm set 用來設置環境變量
1
2
3
4github
$ npm
set
init-author-
name
'Your name'
$ npm
set
init-author-email
'Your email'
$ npm
set
init-author-url
'https://yourdomain.com'
$ npm
set
init-license
'MIT'
上面命令等於爲 npm init 設置了默認值,之後執行 npm init 的時候,package.json 的做者姓名、郵件、主頁、許可證字段就會自動寫入預設的值。這些信息會存放在用戶主目錄的 ~/.npmrc文件,使得用戶不用每一個項目都輸入。若是某個項目有不一樣的設置,能夠針對該項目運行 npm config。
npm info npm info 命令能夠查看每一個模塊的具體信息。好比,查看 underscore 模塊的信息。
1
$ npm info underscore
上面命令返回一個 JavaScript 對象,包含了 underscore 模塊的詳細信息。這個對象的每一個成員,均可以直接從 info 命令查詢。
1
2
3
4
5
$ npm info underscore description
$ npm info underscore homepage
$ npm info underscore version
npm search npm search 命令用於搜索 npm 倉庫,它後面能夠跟字符串,也能夠跟正則表達式。
1
$ npm search <搜索詞>
npm list npm list 命令以樹形結構列出當前項目安裝的全部模塊,以及它們依賴的模塊。
1
2
3
4
5
6
7
$ npm list
# 加上
global
參數,會列出全局安裝的模塊
$ npm list -
global
# npm list 命令也能夠列出單個模塊
$ npm list underscore
npm install 使用 npm 安裝包的命令格式爲:
npm [install/i] [package_name]
本地模式和全局模式 npm 在默認狀況下會從 https://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 本地模式 是 否 全局模式 否 是
1
2
3
4
5
6
# 本地安裝
$ npm install <package
name
=
""
>
# 全局安裝
$ sudo npm install -
global
<package
name
=
""
>
$ sudo npm install -g <package
name
=
""
></package></package></package>
npm install 也支持直接輸入 Github 代碼庫地址。
1
2
$ 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 參數。
1
$ npm install <packagename>
--force</packagename>
安裝不一樣版本 install 命令老是安裝模塊的最新版本,若是要安裝模塊的特定版本,能夠在模塊名後面加上 @ 和版本號。
1
2
3
$ npm install sax@latest
$ npm install sax@0.1.1
$ npm install sax@
">=0.1.0 <0.2.0"
install 命令可使用不一樣參數,指定所安裝的模塊屬於哪種性質的依賴關係,即出如今 packages.json 文件的哪一項中。
–save:模塊名將被添加到 dependencies,能夠簡化爲參數-S。
–save-dev:模塊名將被添加到 devDependencies,能夠簡化爲參數-D。
1
2
3
4
5
$ npm install sax
--save
$ npm install node-tap
--save-dev
# 或者
$ npm install sax -S
$ npm install node-tap -D
dependencies 依賴 這個能夠說是咱們 npm 核心一項內容,依賴管理,這個對象裏面的內容就是咱們這個項目所依賴的 js 模塊包。下面這段代碼表示咱們依賴了 markdown-it 這個包,版本是 ^8.1.0 ,表明最小依賴版本是 8.1.0 ,若是這個包有更新,那麼當咱們使用 npm install 命令的時候,npm 會幫咱們下載最新的包。當別人引用咱們這個包的時候,包內的依賴包也會被下載下來。
1
2
3
"dependencies"
: {
"markdown-it"
:
"^8.1.0"
}
devDependencies 開發依賴 在咱們開發的時候會用到的一些包,只是在開發環境中須要用到,可是在別人引用咱們包的時候,不會用到這些內容,放在 devDependencies 的包,在別人引用的時候不會被 npm 下載。
1
2
3
4
5
6
7
8
9
10
11
"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 字段的模塊。
1
2
3
$ npm install
--production
# 或者
$ NODE_ENV=production npm install
一旦安裝了某個模塊,就能夠在代碼中用 require 命令加載這個模塊。
1
2
var backbone = require(
'backbone'
)
console.log(backbone.VERSION)
npm run npm 不只能夠用於模塊管理,還能夠用於執行腳本。package.json 文件有一個 scripts 字段,能夠用於指定腳本命令,供 npm 直接調用。
package.json
1
2
3
4
5
6
7
8
9
10
11
12
{
"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 的縮寫,通常都使用前者,可是後者能夠更好的反應這個命令的本質。
1
2
3
4
5
6
7
8
9
// 腳本
"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。
1
"build"
:
"npm run build-js && npm run build-css"
上面的寫法是先運行 npm run build-js ,而後再運行 npm run build-css ,兩個命令中間用 && 鏈接。若是但願兩個命令同時平行執行,它們中間能夠用 & 鏈接。
寫在 scripts 屬性中的命令,也能夠在 node_modules/.bin 目錄中直接寫成 bash 腳本。下面是一個 bash 腳本。
1
2
3
4
#!/bin/bash
cd site/main
browserify browser/main.js | uglifyjs -mc >
static
/bundle.js
假定上面的腳本文件名爲 build.sh ,而且權限爲可執行,就能夠在 scripts 屬性中引用該文件。
1
"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。
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"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,會按下面的順序執行相應的命令。
# 項目根目錄下執行
$ npm bin
./node_modules/.bin
建立全局連接 npm 提供了一個有趣的命令 npm link,它的功能是在本地包和全局包之間建立符號連接。咱們說過使用全局模式安裝的包不能直接經過 require 使用。但經過 npm link 命令能夠打破這一限制。舉個例子,咱們已經經過 npm install -g express 安裝了 express,這時在工程的目錄下運行命令:
1
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 文件中修改 version 字段,而後從新使用 npm publish 命令就好了。
若是你對已發佈的包不滿意,可使用 npm unpublish 命令來取消發佈。
須要說明的是:json 文件不能有註釋
個人經常使用命令
1
2
3
npm version 查看npm和node的版本
npm list
--depth=0 [-g] 查看[全局]安裝的包
npm root [-g] 查看[全局的]包的安裝路徑
轉載於猿2048:➞《前端十萬個爲何(之一):咱們爲何須要npm?》