1.包的安裝
安裝(install)即下載包 由於 npm 的官方 registry 服務器位於國外,可能受網速影響導致下載緩慢或失敗。因此,安裝好 npm 之後,需要重新設置 registry 的地址爲國內地址。目前,淘寶 https://registry.npm.taobao.org 提供了國內的 registry 地址,先設置到該地址。設置方式爲npm config set registry https://registry.npm.taobao.org。設置好後,通過命令npm config get registry進行檢查npm 安裝一個包,分爲兩種安裝方式:
本地安裝
全局安裝
本地安裝
使用命令npm install 包名或npm i 包名即可完成本地安裝
本地安裝的包出現在當前目錄下的node_modules目錄中
隨着開發的進展,node_modules目錄會變得異常龐大,目錄下的內容不適合直接傳輸到生產環境,因此通常使用.gitignore文件忽略該目錄中的內容 本地安裝適用於絕大部分的包,它會在當前目錄及其子目錄中發揮作用 通常在項目的根目錄中使用本地安裝 安裝一個包的時候,npm 會自動管理依賴,它會下載該包的依賴包到node_modules目錄中 如果本地安裝的包帶有 CLI,npm 會將它的 CLI 腳本文件放置到node_modules/.bin下,使用命令npx 命令名即可調用
全局安裝
全局安裝的包放置在一個特殊的全局目錄,該目錄可以通過命令npm config get prefix查看
使用命令npm install --global 包名 或 npm i -g 包名
重要:全局安裝的包並非所有工程可用,它僅提供全局的 CLI 工具
大部分情況下,都不需要全局安裝包,除非:
包的版本非常穩定,很少有大的更新
提供的 CLI 工具在各個工程中使用的非常頻繁
CLI 工具僅爲開發環境提供支持,而非部署環境
2.包配置
目前遇到的問題:
拷貝工程後如何還原?
如何區分開發依賴和生產依賴?
如果自身的項目也是一個包,如何描述包的信息
以上這些問題都需要通過包的配置文件解決
配置文件
npm 將每個使用 npm 的工程本身都看作是一個包,包的信息需要通過一個名稱固定的配置文件來描述
配置文件的名稱固定爲:package.json
可以手動創建該文件,而更多的時候,是通過命令npm init創建的
配置文件中可以描述大量的信息,包括:
name:包的名稱,該名稱必須是英文單詞字符,支持連接符
version:版本
版本規範:主版本號.次版本號.補丁版本號
主版本號:僅當程序發生了重大變化時纔會增長,如新增了重要功能、新增了大量的API、技術架構發生了重大變化
次版本號:僅當程序發生了一些小變化時纔會增長,如新增了一些小功能、新增了一些輔助型的API
補丁版本號:僅當解決了一些 bug 或 進行了一些局部優化時更新,如修復了某個函數的 bug、提升了某個函數的運行效率
或者直接npm init --yes
description:包的描述
homepage:官網地址
author:包的作者,必須是有效的 npm 賬戶名,書寫規範是 account ,例如:zhangsan [email protected],不正確的賬號和郵箱可能導致發佈包時失敗
repository:包的倉儲地址,通常指 git 或 svn 的地址,它是一個對象
type:倉儲類型,git 或 svn
url:地址
main:包的入口文件,使用包的人默認從該入口文件導入包的內容
keywords: 搜索關鍵字,發佈包後,可以通過該數組中的關鍵字搜索到包
使用npm init --yes或npm init -y可以在生成配置文件時自動填充默認配置
保存依賴關係
大部分時候,我們僅僅是開發項目,並不會把它打包發佈出去,儘管如此,我們仍然需要package.json文件
package.json文件最重要的作用,是記錄當前工程的依賴
dependencies:生產環境的依賴包
devDependencies:僅開發環境的依賴包
配置好依賴後,使用下面的命令即可安裝依賴
本地安裝所有依賴 dependencies + devDependencies
npm install
npm i
僅安裝生產環境的依賴 dependencies
npm install --production
這樣一來,代碼移植就不是問題了,只需要移植源代碼和package.json文件,不用移植node_modules目錄,然後在移植之後通過命令即可重新恢復安裝
爲了更加方便的添加依賴,npm支持在使用install命令時,加入一些額外的參數,用於將安裝的依賴包保存到package.json文件中
涉及的命令如下
安裝依賴到生產環境
npm i 包名
npm i --save 包名
npm i -S 包名
安裝依賴到開發環境
npm i --save-dev 包名
npm i -D 包名
自動保存的依賴版本,例如^15.1.3,這種書寫方式叫做語義版本號(semver version)。
3.包的使用
nodejs 對 npm 支持非常良好
當使用 nodejs 導入模塊時,如果模塊路徑不是以 ./ 或 …/ 開頭,則 node 會認爲導入的模塊來自於 node_modules 目錄,例如:
var _ = require("lodash");
它首先會從當前目錄的以下位置尋找文件
node_modules/lodash.js
node_modules/lodash/入口文件
若當前目錄沒有這樣的文件,則會回溯到上級目錄按照同樣的方式查找
如果到頂級目錄都無法找到文件,則拋出錯誤
上面提到的入口文件按照以下規則確定
查看導入包的package.json文件,讀取main字段作爲入口文件
若不包含main字段,則使用index.js作爲入口文件
入口文件的規則同樣適用於自己工程中的模塊 在 node 中,還可以手動指定路徑來導入相應的文件,這種情況比較少見
2-5語義版本
思考:如果你編寫了一個包A,依賴另外一個包B,你在編寫代碼時,包B的版本是2.4.1,你是希望使用你包的人一定要安裝包B,並且是2.4.1版本,還是希望他可以安裝更高的版本,如果你希望它安裝更高的版本,高的什麼程度呢?回顧:版本號規則
版本規範:主版本號.次版本號.補丁版本號
主版本號:僅當程序發生了重大變化時纔會增長,如新增了重要功能、新增了大量的API、技術架構發生了重大變化
次版本號:僅當程序發生了一些小變化時纔會增長,如新增了一些小功能、新增了一些輔助型的API
補丁版本號:僅當解決了一些 bug 或 進行了一些局部優化時更新,如修復了某個函數的 bug、提升了某個函數的運行效率
有的時候,我們希望:安裝我的依賴包的時候,次版本號和補丁版本號是可以有提升的,但是主版本號不能變化
有的時候,我們又希望:安裝我的依賴包的時候,只有補丁版本號可以提升,其他都不能提升
甚至我們希望依賴包保持固定的版本,儘管這比較少見
這樣一來,就需要在配置文件中描述清楚具體的依賴規則,而不是直接寫上版本號那麼簡單。
這種規則的描述,即語義版本
語義版本的書寫規則非常豐富,下面列出了一些常見的書寫方式
符號 描述 示例 示例描述
大於某個版本 >1.2.1 大於1.2.1版本
= 大於等於某個版本 >=1.2.1 大於等於1.2.1版本
< 小於某個版本 <1.2.1 小於1.2.1版本
<= 小於等於某個版本 <=1.2.1 小於等於1.2.1版本
- 介於兩個版本之間 1.2.1 - 1.4.5 介於1.2.1和1.4.5之間
x 不固定的版本號 1.3.x 只要保證主版本號是1,次版本號是3即可
~ 補丁版本號可增 ~1.3.4 保證主版本號是1,次版本號是3,補丁版本號大於等於4
^ 此版本和補丁版本可增 ^1.3.4 保證主版本號是1,次版本號可以大於等於3,補丁版本號可以大於等於4
- 最新版本 * 始終安裝最新版本
避免還原的差異
版本依賴控制始終是一個兩難的問題
如果允許版本增加,可以讓依賴包的bug得以修復(補丁版本號),可以帶來一些意外的驚喜(次版本號),但同樣可能帶來不確定的風險(新的bug)
如果不允許版本增加,可以獲得最好的穩定性,但失去了依賴包自我優化的能力
而有的時候情況更加複雜,如果依賴包升級後,依賴也發生了變化,會有更多不確定的情況出現
基於此,npm 在安裝包的時候,會自動生成一個 package-lock.json 文件,該文件記錄了安裝包時的確切依賴關係
當移植工程時,如果移植了 package-lock.json 文件,恢復安裝時,會按照 package-lock.json 文件中的確切依賴進行安裝,最大限度的避免了差異
[擴展]npm的差異版本處理
如果兩個包依賴同一個包的不同版本,如下圖
面對這種情況,在 node_modules 目錄中,不會使用扁平的目錄結構,而會形成嵌套的目錄,如下圖:
├── node_modules
│ ├── a
│ │ ├── node_modules
│ │ │ ├── c
│ │ │ | |—— c包的文件
│ │ │── a包的文件
│ ├── b
│ │ ├── node_modules
│ │ │ ├── c
│ │ │ | |—— c包的文件
│ │ │── b包的文件
2-6npm 腳本 (npm scripts)
在開發的過程中,我們可能會反覆使用很多的 CLI 命令,例如: ![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200309201454522.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMTc3NDc4,size_16,color_FFFFFF,t_70)啓動工程命令(node 或 一些第三方包提供的CLI命令)
部署工程命令(一些第三方包提供的CLI命令)
測試工程命令(一些第三方包提供的CLI命令)
這些命令紛繁複雜,根據第三方包的不同命令也會不一樣,非常難以記憶
於是,npm 非常貼心的支持了腳本,只需要在 package.json 中配置 scripts 字段,即可配置各種腳本名稱
之後,我們就可以運行簡單的指令來完成各種操作了
運行方式是 npm run 腳本名稱
不僅如此,npm 還對某些常用的腳本名稱進行了簡化,下面的腳本名稱是不需要使用run的:
start
stop
test
一些細節:
腳本中可以省略npx
start腳本有默認值:node server.js
2-7運行環境配置
我們書寫的代碼一般有三種運行環境:開發環境
生產環境
測試環境
有的時候,我們可能需要在 node 代碼中根據不同的環境做出不同的處理
如何優雅的讓 node 知道處於什麼環境,是極其重要的
通常我們使用如下的處理方式:
node中有一個全局變量 global (可以類比瀏覽器環境的window),該變量是一個對象,對象中的所有屬性均可以直接使用
global有一個屬性是process,該屬性是一個對象,包含了當前運行node程序的計算機的很多信息,其中有一個信息是env,是一個對象,包含了計算機中所有的系統變量
通常,我們通過系統變量 NODE_ENV 的值,來判定node程序處於何種環境
有兩種方式設置 NODE_ENV 的值
永久設置
臨時設置
我們一般使用臨時設置
因此,我們可以配置 scripts 腳本,在設置好了 NODE_ENV 後啓動程序
爲了避免不同系統的設置方式的差異,可以使用第三方庫 cross-env 對環境變量進行設置
在node中讀取package.json
有的時候,我們可能在 package.json 中配置一些自定義的字段,這些字段需要在node中讀取
在node 中,可以直接導入一個json格式的文件,它會自動將其轉換爲js對象
2-8其他npm命令 {ignore}
**安裝**精確安裝最新版本
npm install --save-exact 包名
npm install -E 包名
安裝指定版本
npm install 包名@版本號
查詢
查詢包安裝路徑
npm root [-g]
查看包信息
npm view 包名 [子信息]
view aliases:v info show
查詢安裝包
npm list [-g] [--depth=依賴深度]
list aliases: ls la ll
更新
檢查有哪些包需要更新
npm outdated
更新包
npm update [-g] [包名]
update 別名(aliases):up、upgrade
卸載包
npm uninstall [-g] 包名
uninstall aliases: remove, rm, r, un, unlink
npm 配置
npm的配置會對其他命令產生或多或少的影響
安裝好npm之後,最終會產生兩個配置文件,一個是用戶配置,一個是系統配置,當兩個文件的配置項有衝突的時候,用戶配置會覆蓋系統配置
通常,我們不關心具體的配置文件,而只關心最終生效的配置
通過下面的命令可以查詢目前生效的各種配置
npm config ls [-l] [--json]
另外,可以通過下面的命令操作配置
獲取某個配置項
npm config get 配置項
設置某個配置項
npm config set 配置項=值
移除某個配置項
npm config delete 配置項
2-9發佈包
準備工作
移除淘寶鏡像源
到npm官網註冊一個賬號,並完成郵箱認證
本地使用 npm cli 進行登錄
使用命令npm login登錄
使用命令npm whoami查看當前登錄的賬號
使用命令npm logout註銷
創建工程根目錄
使
用npm init進行初始化
發佈
開發
確定版本
使用命令npm publish完成發佈
3-2yarn 的核心命令
初始化初始化:yarn init [--yes/-y]
安裝
添加指定包:yarn [global] add package-name [--dev/-D] [--exact/-E]
安裝package.json中的所有依賴:yarn install [--production/--prod]
腳本和本地CLI
運行腳本:yarn run 腳本名
start、stop、test可以省略run
運行本地安裝的CLI:yarn run CLI名
查詢
查看bin目錄:
yarn [global] bin
查詢包信息:yarn info 包名 [子字段]
列舉已安裝的依賴:yarn [global] list [--depth=依賴深度]
yarn的list命令和npm的list不同,yarn輸出的信息更加豐富,包括頂級目錄結構、每個包的依賴版本號
更新
列舉需要更新的包:yarn outdated
更新包:yarn [global] upgrade [包名]
卸載
卸載包:yarn remove 包名
3-3yarn 的特別禮物
在終端命令上,yarn不僅僅是對npm的命令做了一個改名,還增加了一些原本沒有的命令,這些命令在某些時候使用起來非常方便yarn check
使用yarn check命令,可以驗證package.json文件的依賴記錄和lock文件是否一致
這對於防止篡改非常有用
yarn audit
使用yarn audit命令,可以檢查本地安裝的包有哪些已知漏洞,以表格的形式列出,漏洞級別分爲以下幾種:
INFO:信息級別
LOW: 低級別
MODERATE:中級別
HIGH:高級別
CRITICAL:關鍵級別
yarn why
使用yarn why 包名命令,可以在控制檯打印出爲什麼安裝了這個包,哪些包會用到它
yarn create
非常有趣的命令
今後,我們會學習一些腳手架,所謂腳手架,就是使用一個命令來搭建一個工程結構
過去,我們都是使用如下的做法:
全局安裝腳手架工具
使用全局命令搭建腳手架
由於大部分腳手架工具都是以create-xxx的方式命名的,比如react的官方腳手架名稱爲create-react-app
因此,可以使用yarn create命令來一步完成安裝和搭建
例如:
yarn create react-app my-app
等同於下面的兩條命令
yarn global add create-react-app
create-react-app my-app
4-1cnpm
官網地址:https://npm.taobao.org/爲解決國內用戶連接npm registry緩慢的問題,淘寶搭建了自己的registry,即淘寶npm鏡像源
過去,npm沒有提供修改registry的功能,因此,淘寶提供了一個CLI工具即cnpm,它支持除了npm publish以外的所有命令,只不過連接的是淘寶鏡像源
如今,npm已經支持修改registry了,可能cnpm唯一的作用就是和npm共存,即如果要使用官方源,則使用npm,如果使用淘寶源,則使用cnpm
4-2nvm
nvm並非包管理器,它是用於管理多個node版本的工具在實際的開發中,可能會出現多個項目分別使用的是不同的node版本,在這種場景下,管理不同的node版本就顯得尤爲重要
nvm就是用於切換版本的一個工具
下載和安裝
最新版下載地址:https://github.com/coreybutler/nvm-windows/releases
下載nvm-setup.zip後,直接安裝
使用nvm
nvm提供了CLI工具,用於管理node版本
在終端中輸入nvm,以查看各種可用命令
爲了加快下載速度,建議設置淘寶鏡像 node淘寶鏡像:https://npm.taobao.org/mirrors/node/ npm淘寶鏡像:https://npm.taobao.org/mirrors/npm/
pnpm
pnpm是一種新起的包管理器,從npm的下載量看,目前還沒有超過yarn,但它的實現方式值得主流包管理器學習,某些開發者極力推薦使用pnpm
從結果上來看,它具有以下優勢:
目前,安裝效率高於npm和yarn的最新版
極其簡潔的node_modules目錄
避免了開發時使用間接依賴的問題
能極大的降低磁盤空間的佔用
安裝和使用
全局安裝pnpm
4-3npm install -g pnpm
之後在使用時,只需要把npm替換爲pnpm即可如果要執行安裝在本地的CLI,可以使用pnpx,它和 npx 的功能完全一樣,唯一不同的是,在使用pnpx執行一個需要安裝的命令時,會使用pnpm進行安裝
比如npx mocha執行本地的mocha命令時,如果mocha沒有安裝,則npx會自動的、臨時的安裝mocha,安裝好後,自動運行mocha命令
pnpm原理
同 yarn 和 npm 一樣,pnpm 仍然使用緩存來保存已經安裝過的包,以及使用 pnpm-lock.yaml 來記錄詳細的依賴版本
不同於 yarn 和 npm, pnpm 使用符號鏈接和硬鏈接(可將它們想象成快捷方式)的做法來放置依賴,從而規避了從緩存中拷貝文件的時間,使得安裝和卸載的速度更快
由於使用了符號鏈接和硬鏈接,pnpm可以規避windows操作系統路徑過長的問題,因此,它選擇使用樹形的依賴結果,有着幾乎完美的依賴管理。也因爲如此,項目中只能使用直接依賴,而不能使用間接依賴
注意事項
由於 pnpm 會改動 node_modules 目錄結構,使得每個包只能使用直接依賴,而不能使用間接依賴,因此,如果使用 pnpm 安裝的包中包含間接依賴,則會出現問題(現在不會了,除非使用了絕對路徑)
由於 pnpm 超高的安裝卸載效率,越來越多的包開始修正之前的間接依賴代碼