前端包管理器

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 超高的安裝卸載效率,越來越多的包開始修正之前的間接依賴代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章