npm總結(一)

本文參考:


前言

隨著前端工程的發展,npm已然成為每個前端開發者的必備技能,然而大多數人對它的使用也只是停留在使用npm安裝一些依賴包而已。作為全世界最大規模的包管理器,每周大約有30億次的下載量,npm的功能遠不止安裝依賴這么簡單,本文的目的就是介紹npm更多的功能。

tips:本文 demo 倉庫:npm-demo

1. 安裝 npm 和管理 npm 版本

npm是NodeJS自帶的一個包管理工具,在 NodeJS官網 安裝NodeJS后即可使用npm

  • 查看npm版本
$ npm -v
  • 更新npm版本
$ npm install npm@latest -g

2. npm init

該命令的原理是調用腳本(init-package-json),輸出一個初始化的package.json文件,package.json中記錄了項目中的依賴包的信息(如名稱、版本等)。

npm init
package.json

執行npm init每次都會輸入如上信息,可以使用npm init --yes快速創建一個帶有默認信息的package.json的文件。

3. 安裝依賴包

安裝依賴包是npm的核心功能,輸入npm installnpm會自動從package.json文件中尋找dependenciesdevDependencies下的依賴包,并安裝到項目的node-modules文件夾下。

3.1 關于 package

當手動安裝一個依賴包時,使用npm install <package>命令即可安裝,參數package即是要安裝的依賴包名,一般npm會在 默認源倉庫 中去查找對應的包名。然而,package不光是一個包名,還有更多的定義方式,參見:Understanding Packages and Modules,以下是package定義的規則:

  1. 包含package.json文件描述該程序的文件夾
custom local package
custom local package 安裝
  1. 滿足規則(1)的gzip壓縮文件
gzip 壓縮文件
  1. 可以下載到規則(2)資源的url鏈接
url 鏈接
  1. 格式為<name>@<version>,一般是已發布在npm源倉庫上的可訪問 url,且該url滿足規則(3)
<name>@<version>
  1. 格式為<name>@<tag>,通過tag標記獲取到version,且滿足規則(4)
<name>@<tag>
  1. 格式為<name>,默認添加latest標記獲取最新發布版,且滿足規則(5)
<name>
  1. 滿足規則(1)的git urlgit url 支持格式
git url

按照以上不同規則安裝后的package.json文件如下:

package.json

注意:無論以何種方式安裝依賴包,npm install時都會去根據package.json文件中的dependencies字段下載它所依賴的相關包

3.2 本地包應用場景

場景模擬如下所示:

  1. 創建一個公共模塊common-package-test,存放項目中一些公共的配置或方法
公共模塊
  1. src目錄下創建一個輪播圖列表組件
輪播圖組件
  1. 利用webpack打包該文件,并進行測試
webpack 打包
  1. 打開index.html,查看控制臺,正常輸出
控制臺輸出

通過以上場景模擬,內容可以正常輸出,但是問題在于引用路徑一直往上層尋找,這種引用很不利于項目的維護。而且公共模塊也確實需要單獨分離出來給其他模塊引用,為了更優雅的引用,可以利用npm本地包將公共模塊封裝到node_modules中。

解決方案:

  1. 在公共模塊common-package-test下創建一個package.json文件
公共模塊 package.json
  1. 利用npm安裝本地包
安裝本地包
  1. 在輪播圖組件重新引入common-package-test模塊
引入 common-package-test 模塊
  1. 通過 webpack 打包進行測試
控制臺輸出

3.3 遠程 git 倉庫包應用場景

場景:使用一個npm包時發現它有bug,也找出了它的問題,并直接在node_modules中修復了它,這樣并沒有用。因為在.gitignore文件一般會忽略提交node_modules,即node_modules不在版本控制內,即使修復了它,下次下載依賴是還是會覆蓋修復。

解決:先在git倉庫中fork要修復的npm包,然后在自己的倉庫中修復該問題,最后在package.json中引用自己的git url即可解決問題。

4. 工作原理

  • npm2采用的是遞歸安裝的方法,當項目較復雜時,目錄結構也會很深,會出現超出windows系統中路徑超過260字符的錯誤;部分相同的依賴包也會被重復安裝,造成大量冗余。
  • npm3采用扁平結構優化解決了以上問題,但也導致了npm依賴樹不能和文件結構所對應了,可以通過npm ls來查看模塊間的依賴關系。
  • npm5依然采用扁平結構,還引入了package-lock.json文件,它可以鎖定依賴的安裝結構和版本等信息。
package-lock.json

package-lock.json文件主要由versionresolvedintegrityrequiresdependencies幾個字段組成。

  • version:包的準確版本號
  • resolved:安裝源
  • integrity:完整哈希
  • requires:除最外層的requires屬性為true, 其他的requires屬性都對應著該依賴包中的package.json里記錄的自己的依賴項
  • dependencies:與node_modules文件結構有著一一對應的關系。

使用package-lock.json的好處在于可以鎖定安裝的依賴包,在另外一臺設備上下載依賴會按照鎖定版本去下載,這樣就不會因為依賴包版本不同而導致一些意外的問題。

5. 依賴包版本管理

5.1 semver

  1. npm采用語義化版本 (semver) 規范進行版本管理。

版本格式:主版本號.次版本號.修訂號,版本號遞增規則如下:

  • 主版本號:做了不兼容的 API 修改
  • 次版本號:做了向下兼容的功能性新增,
  • 修訂號:做了向下兼容的問題修正。
  1. npm提供了網站 npm semver calculator ,可以方便地計算semver的匹配范圍。下面列舉一些規則示例:
  • ^4.1.3:指定的主版本號下,所有更新的版本
  • ~4.1.3:指定的次版本號下,所有更新的版本
  • >4.1.3:版本號大于4.1.3
  • <=4.3:版本號小于等于4.3
  • 3.1.0 - 4.2.1:版本號在3.1.04.2.1之間
  • >=3.3.1 <3.8.0:與邏輯,版本號大于等于3.3.1且小于3.8.0
  • >4.3.1 || <=2.3.1:或邏輯,版本號大于4.3.1或小于等于2.3.1
  • *:所有主版本
  • 22.*2.x:主版本號為2的所有版本
  • 3.33.3.*3.3.x:版本號為3.3開頭的所有版本
  • 5.0.0-alpha:預發布版本
  • 7.0.0-beta.3:預發布版本
  • 1.0.0-rc.3:預發布版本

5.2 依賴包管理建議

  1. 使用npm5.2以上的版本,保留package-lock.json文件
  2. 不要手動修改package-lock.json
  3. 升級小版本依賴包:npm update <package>
  4. 升級大版本依賴包: npm install <package>@<version>
  5. 降級依賴包:npm install <package>@<version>
  6. 刪除依賴包:npm uninstall <package>
  7. 當提交了package.jsonpackage-lock.json的更新后,應及時拉取更新,并重新npm install重新安裝更新后的依賴

6. npm 腳本

6.1 npm scripts

  1. 使用npm scripts可以在package.json文件中自定義腳本
{
  "script": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

以上代碼片段是create-react-app腳手架生成的React項目中的scripts,可以使用npm run命令來執行上面的scripts,執行npm run build就等同于執行對應的npm腳本:react-scripts build

  1. npm腳本原理

當執行npm run命令時,會自動新建一個shell去執行里面的腳本,shell會將./node_modules./bin目錄添加到PATH變量中。也就是說,如果./node_modules./.bin目錄中的腳本,可以直接調用腳本名,不用去寫完整的腳本路徑或是全局安裝腳本了。

  1. 簡寫
  • npm startnpm run start的簡寫
  • npm stopnpm run stop的簡寫
  • npm testnpm run test的簡寫
  • npm restartnpm run stop && npm run restart && npm run start的簡寫
  1. 變量

npm腳本可以通過環境變量process.env的方式獲取到運行時的相關變量:

{
  "name": "webpack",
  "version": "3.8.1",
  "repository": {
    "type": "git",
    "url": "https://github.com/webpack/webpack.git"
  }
}

上面的代碼片段是webpackpackage.json文件中的部分內容,可以通過process.env對象獲取其中的變量。
例如:process.env.npm_package_name返回webpackprocess.env.npm_package_version返回3.8.1process.env.npm_package_repository_type返回git

6.2 npx

  1. 先舉個例子,在npm5.2版本以前,如果只是在項目中安裝了webpack,打包的時候就需要用./node_modules./.bin/webpack來調用webpack命令來進行打包。調用命令時每次都要輸入這么長的路徑,會覺得很麻煩,所以一般會在全局安裝webpackwebpack-cli,然后直接用webpack命令來打包,這是因為在webpackpackage.json文件中有對bin字段的定義:
"bin": {
  "webpack": "./bin/webpack.js"
}

但是全局安裝的webpack命令可能會與項目使用的weboack命令版本不同,也會導致不能成功構建。上一節講到了npm scripts,這時我們就可以將webpack命令寫到npm scripts中,而不需要全局安裝了,因為npm run命令能夠在執行時把./node_modules/.bin加入到PATH變量中,進而直接調用webpack命令了

npm5.2版本以后,npx很方便地解決了上述問題,直接使用npx webpack就可以去自動尋找項目中安裝好的webpack依賴包,然后進行打包

  1. 執行遠程npm遠的二進制包

npm5.2版本以前,初始化React腳手架項目,需要現在全局安裝create-react-app,然后再創建初始化的項目:

npm install -g create-react-app
create-react-app my-app

npm5.2版本后,直接使用npx即可安裝并創建初始化項目,這樣也就不必全局安裝create-react-app了,也不必去檢查全局安裝的依賴包版本是否過低:

npx create-react-app my-app

6.3 切換不同的Node版本

在以前都是用 nvmn 這樣的Node版本管理工具來切換Node版本,而有了npx同樣可以在不手動切換Node的前提下,使用不同的Node版本環境:

npx 切換 Node 版本

7. npm 配置

7.1 npm-config

通過npm config ls -l可以查看npm的所有配置,詳細的配置說明可在官方文檔查看:config | npm Documentation

npm comfig

修改配置命令:npm config set <key> <value>
修改npm倉庫源為淘寶鏡像源:npm config set registry https://registry.npmjs.org/

7.2 .npmrc文件

上面的修改npm配置是借助命令行來完成的,除了命令還可以通過.npmrc文件來修改配置。

npm讀取config配置的優先級:

  • 工程目錄下的.npmrc文件(/path/to/my/project/.npmrc
  • 用戶配置文件(~/.npmrc
  • 全局配置文件($PREFIX/etc/npmrc
  • npm內置的配置文件(/path/to/npm/npmrc

8. 總結

  • 為了統一配置,項目中的npm config添加到.npmrc文件中
  • 統一node運行環境,package.jsonpackage-lock.json文件
  • 合理使用安裝依賴包:npm install <package>|<local file>|<git url>
  • 使用npm5.2以上版本
  • 合理使用npm scriptsnpx管理應用相關腳本

npm的一些基礎使用和介紹先到此為止,關于更加詳細的使用和其他高級用法請看下一篇文章:npm總結(二)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370