(前端工程化01)私人管家-包管理器

字數:3883, 閱讀時間:10分鐘,點擊閱讀原文
目錄:html

點擊查看源網頁

包管理器

在好久好久之前,那時候的前端被你們」親切「的稱爲「切圖仔」,那時前端的工做很是簡單,僅僅只是將設計圖還原,而後加上一些交互和特效。因爲沒有分享的平臺,項目中不少本身寫的東西分享出來也比較困難,代碼的複用也只能是手動CV。即便用到了第三方的一些插件,好比jQuery,也只能下載後手動進行管理。前端

後來,nodejs出現了,做爲一門後端語言,它的複雜程度遠比前端要高得多,若是手動管理那將是一件很痛苦的事情,因此npm應運而生。vue

下面咱們簡單介紹一下幾個概念:node

  • 包:包便是一段能複用的代碼,它能夠存在開發者本地和雲端,每一個包可能依賴也可能不會依賴其餘包
  • 包管理器:對包進行管理的工具,能夠追溯包的版本、依賴、做者等相關信息,還能夠將雲端的包下載到本地。

NPM

npm即Node package Manager,軟件開發者可在上面分享本身的成果,包含上百萬個包,並且使用它能夠輕鬆跟蹤依賴和版本。react

npm主要有三個部分組成:git

  • 網站:開發者查找包(package)的主要途徑,能夠經過不一樣的條件進行檢索,還能夠管理本身或組織的帳戶
  • 註冊表:一個巨大的數據庫,保存了每一個包(package)的相關信息
  • 命令行工具:經過命令行終端運行

NPM會在安裝NodeJS的時候附帶安裝,具體的安裝及配置請見上一篇《開發環境搭建》。github

經常使用命令

生成配置文件package.json

npm init [配置]

配置:web

  • -y(--yes) :跳過問答模式,全部配置所有選擇默認配置

搜索包

npm search <包名>

注意: 搜索包須要切換到npm官方鏡像源typescript

npm包的開發門檻很低,數量衆多,重複的輪子也多得出奇,每次選擇一個包對我這種選擇強迫症來講,不是一件容易的事情,通常咱們能夠參考如下幾點:shell

  • 下載量,相信別人的選擇
  • 維護的活躍程度,包括最後更新時間,是否能夠給做者提交issues
  • 文檔,沒文檔就是在看天書

安裝包

npm install <包名> [配置] # install 能夠簡寫爲i

配置:

  • -g (--global):將包做爲全局依賴安裝,通常命令行工具之類的會選擇此方式
  • -S (--save):將包做爲生產依賴安裝,通常在生成(線上)環境使用的依賴都採用此方式,默認也是此方式
  • -D (--save-dev):將包做爲開發依賴安裝,通常開發環境使用的一些工具都採用此方式安裝

能夠在包名後面加上版本號以安裝特定版本號,如npm install vue@2.16.1

卸載包

npm uninstall <包名> [配置]

配置和安裝包配置同樣,不一樣配置表示寫在不一樣地方的包

更新包

npm update <包名> [配置]

配置和安裝包配置同樣,不一樣配置表示寫在不一樣地方的包

發佈包

npm publish [配置]

配置:

  • --tag beta: 指定標籤,默認爲版本號,可以使用npm publish --tag beta安裝

安全檢測

npm audit # 對包及其依賴進行安全監測,並生成報告
npm audit fix # 自動爲易受攻擊的依賴項安裝兼容的更新
npm set audit false # 關閉監測機制

因爲npm包的數量衆多,並且不少包早已沒有維護了,不免會出現一些安全問題,因此安全監測能夠幫助咱們作一些排查。

注意:** 安全監測須要切換到npm官方鏡像源

清除緩存

npm cache clean --force #強制清除npm緩存

NPX

npm在5.2版本內置了npx工具,也可使用npm install -g npx手動安裝,主要用來在命令行調用項目內部安裝的模塊,避免安裝一些全局模塊。

  • 調用項目中安裝的包

若是咱們在項目中安裝了gulp,要執行gulp相關的命令,若是在項目目錄下在終端直接執行的話,它會去全局的包查找,若是要避免這種狀況,就只能將命令定義在package.json的scripts中,而後經過npm run的方式來執行。若是使用npx,就會避免這種狀況,由於它會優先去本地項目中尋找。

npx gulp --version
  • 避免全局安裝模塊

通常在使用一些腳手架的時候,咱們須要在全局安裝後纔可以使用。若是使用npx就不須要。

npx create-react-app my-react-app

npx 將create-react-app下載到一個臨時目錄,使用之後再刪除,避免了安裝全局模塊。

  • 執行遠程代碼
# 執行 Gist 代碼
$ npx https://gist.github.com/zkat/4bc19503fe9e9309e2bfaa2c58074d32

# 執行倉庫代碼
$ npx github:piuccio/cowsay hello

參考資料:npx 使用教程

package.json

package.json是npm的配置文件,通常存在於項目的根目錄中,記錄了當前工程信息及使用的依賴包信息。

必填字段
  • name:包的名字,不能以點(.)或下劃線(_)開頭,不能包含中文、大寫字母及非URL安全字符,長度必須小於或等於214個字符,@開頭的包標識它是Scoped包。
  • version:包的當前版本,遵循 Semantic Versioning 2.0.0 語義化版本規範
信息類字段
  • description:包的描述
  • keywords:關鍵字,值爲一個字符串數組,當在搜索包時頗有用
  • license:許可證,以便讓用戶瞭解他們是在什麼受權下使用此包,以及此包還有哪些附加限制。
{
  "license": "MIT",
  "license": "(MIT or GPL-3.0)",
  "license": "SEE LICENSE IN LICENSE_FILENAME.txt",
  "license": "UNLICENSED"
}
連接類字段

各類指向項目文檔、issues 上報,以及代碼託管網站的連接字段。

  • homepage:是包的項目主頁或者文檔首頁。
  • bugs:問題反饋系統的 URL,或者是 email 地址之類的連接。方便用戶經過該途徑向包做者反饋問題。
  • repository:是包代碼託管的位置。
{
  "repository": { "type": "git", "url": "https://github.com/user/repo.git" },
  "repository": "github:user/repo",
  "repository": "gitlab:user/repo",
  "repository": "bitbucket:user/repo",
  "repository": "gist:a1b2c3d4e5f"
}
項目維護類字段

項目的維護者的相關信息。

  • `author:做者信息,一我的。
{
  "author": { "name": "Your Name", "email": "you@example.com", "url": "http://your-website.com" },
  "author": "Your Name <you@example.com> (http://your-website.com)"
}
  • `contributors:貢獻者信息,可能不少人。
{
  "contributors": [
    { "name": "Your Friend", "email": "friend@example.com", "url": "http://friends-website.com" }
    { "name": "Other Friend", "email": "other@example.com", "url": "http://other-website.com" }
  ],
  "contributors": [
    "Your Friend <friend@example.com> (http://friends-website.com)",
    "Other Friend <other@example.com> (http://other-website.com)"
  ]
}
文件類信息

指定包含在項目中的文件,以及項目的入口文件。

  • files:項目包含的文件,能夠是單獨的文件、整個文件夾,或者通配符匹配到的文件。
{
  "files": [
    "filename.js",
    "directory/",
    "glob/*.{js,json}"
  ]
}
  • main:項目的入口文件。
{
  "main": "filename.js"
}
  • bin:隨着項目一塊兒被安裝的可執行文件,開發命令行工具會用到此項。
{
  "bin": "bin.js",
  "bin": {
    "other-command": "bin/other-command"
  }
}
  • man:項目的入口文件。

項目的入口文件。

{
  "man": "./man/doc.1",
  "man": ["./man/doc.1", "./man/doc.2"]
}
  • directories:當你的包安裝時,你能夠指定確切的位置來放二進制文件、man pages、文檔、例子等
{
  "directories": {
    "lib": "path/to/lib/",
    "bin": "path/to/bin/",
    "man": "path/to/man/",
    "doc": "path/to/doc/",
    "example": "path/to/example/"
  }
}
  • types:指定 TypeScript 中的類型聲明文件
{
  "types": "./lib/main.d.ts",
}
任務類字段

腳本是定義自動化開發相關任務的好方法,好比使用一些簡單的構建過程或開發工具。 在 scripts 字段裏定義的腳本,能夠經過npm run xxx 命令來執行。 例如,上述 build-project 腳本能夠經過 npm run build-project 調用,並執行 node build-project.js

{
  "scripts": {
    "build-project": "node build-project.js"
  }
}

有一些特殊的腳本名稱。 若是定義了 preinstall 腳本,它會在包安裝前被調用。 出於兼容性考慮,installpostinstallprepublish 腳本會在包完成安裝後被調用。

特定的 scripts
  • prepublish: 在打包併發布包以前運行,以及在沒有任何參數的本地 npm 安裝以前運行。
  • prepare: 在打包和發佈包以前運行,在沒有任何參數的本地 npm install 上運行,以及安裝 git 依賴項時。 這是在 preublish 以後運行,可是在 preublishOnly 以前運行。
  • prepublishOnly: 在包準備和打包以前運行,僅限於npm發佈。
  • prepack: 在打包 tarball 以前運行(在 npm packnpm publish,以及安裝 git 依賴項時)
  • postpack: 在生成 tarball 以後運行並移動到其最終目標。
  • publish, postpublish: 在包發佈後運行。
  • preinstall: 在安裝軟件包以前運行。
  • install, postinstall: 安裝包後運行。
  • preuninstall, uninstall: 在卸載軟件包以前運行。
  • postuninstall: 在卸載軟件包以後運行。
  • preversion: 在改變包版本以前運行。
  • version: 改變包版本後運行,但提交以前。
  • postversion: 改變包版本後運行,而後提交。
  • pretest, test, posttest: 由 npm test 命令運行。
  • prestop, stop, poststop: 由 npm stop 命令運行。
  • prestart, start, poststart: 由 npm start 命令運行。
  • prerestart, restart, postrestart: 由 npm restart 命令運行。 注意:若是沒有提供重啓腳本,npm restart 將運行 stopstart 腳本。
  • preshrinkwrap, shrinkwrap, postshrinkwrap: 由 npm shrinkwrap 命令運行。
依賴描述類字段

記錄了當前工程或者包的其餘依賴,他們的版本遵循以下規則:

  • 補丁發佈:1.01.0.x~1.0.4
  • 次要版本:11.x^1.0.4
  • 主要版本:*x
  • dependencies:這些是你的包的開發版和發佈版都須要的依賴,使用npm i xxx -S安裝。
{
  "dependencies": {
    "package-1": "^3.1.4",
    "package-2": "file:./path/to/dir"
  }
}
你能夠指定一個確切的版本、一個最小的版本 (好比 >=) 或者一個版本範圍 (好比 >= ... <)。
包也能夠指向本地的一個目錄文件夾。
  • devDependencies:這些是隻在你的包開發期間須要,可是生產環境不會被安裝的包,使用npm i xxx -D安裝。

這些是隻在你的包開發期間須要,可是生產環境不會被安裝的包。

{
  "devDependencies": {
    "package-2": "^0.4.2"
  }
}

咱們再安裝包的時候最好按照使用環境來安裝,不要不分環境隨便安裝,不然在某些狀況下打包會出現問題。

參考資料: package.json 說明文檔

package-lock.json

原則上,包的發佈須要嚴格遵循 語義版本控制 規則,可是這並非一個強制的規則,因此,大多人開發的時候經驗會出現一樣的 package.json 文件,但安裝了不一樣版本的包,這可能致使出現一些兼容錯誤,因此npm在安裝時就會生成lock來鎖定版本。

查找規則

npm包在使用時遵循以下查找規則:

  1. 在當前目錄下查找node_modules目錄;若是沒有則向上一層目錄查找,若是也沒有則繼續向上層目錄查找直到根目錄; 若是都沒有則報錯
  2. 進入node_modules中查找模塊名目錄;若是沒有則報錯
  3. 進入模塊名目錄查找 package.json 文件中的 main 配置項,導入該配置項指定的文件
  4. 若是模塊名目錄中沒有 package.json文件,或package.json文件中沒有 main 配置項,則加載 index.js 文件

Yarn

Yarn 是一個由 Facebook,Google,Exponent 和 Tilde 構建的新的 JavaScript 包管理器。正如官方公告所寫,它的目標就是解決這些團隊使用 npm 的時候所遇到的幾個問題,即:

  • 安裝包不夠快速和穩定
  • 存在安全隱患,由於 npm 容許包在安裝的時候運行代碼

它並非想要徹底替代 npm。Yarn 僅僅是一個可以從 npm 倉庫獲取到模塊的新的 CLI 客戶端。

更清晰的輸出

yarn的輸出很清晰,使用了emoji,看起來也更加漂亮。

「yarn install」 命令的輸出

並行安裝

在安裝多個包時,npm會按包順序執行,也就是隻有當一個包所有安裝完成後,纔會安裝下一個。Yarn 則是並行執行任務,提升了性能。

yarn和npm的命令對比

  • 有區別的命令
Npm Yarn 功能描述
npm install(npm i) yarn install(yarn) 根據 package.json 安裝全部依賴
npm i –save [package] yarn add [package] 添加依賴包
npm i –save-dev [package] yarn add [package] –dev 添加依賴包至 devDependencies
npm i -g [package] yarn global add [package] 進行全局安裝依賴包
npm update –save yarn upgrade [package] 升級依賴包
npm uninstall [package] yarn remove [package] 移除依賴包
  • 相同操做的命令
Npm Yarn 功能描述
npm run yarn run 運行 package.json 中預約義的腳本
npm config list yarn config list 查看配置信息
npm config set registry 倉庫地址 yarn config set registry 倉庫地址 更換倉庫地址
npm init yarn init 互動式建立/更新 package.json 文件
npm list yarn list 查看當前目錄下已安裝的node包
npm login yarn login 保存你的用戶名、郵箱
npm logout yarn logout 刪除你的用戶名、郵箱
npm outdated yarn outdated 檢查過期的依賴包
npm link yarn link 開發時連接依賴包,以便在其餘項目中使用
npm unlink yarn unlink 取消連接依賴包
npm publish yarn publish 將包發佈到 npm
npm test yarn test 測試 = yarn run test
npm bin yarn bin 顯示 bin 文件所在的安裝目錄
yarn info yarn info 顯示一個包的信息

yarn的命令跟npm的命令差別不大,若是使用過npm,那麼過渡到yarn也很簡單。npm自己也在不斷優化,繼續使用也沒有關係。

參考資料:Npm vs Yarn 之備忘詳單

將來

如今npm包仍是有不少沒法迴避的問題,最初node_modules下面每一個依賴包的依賴放在本身的目錄下面,相同的依賴沒法複用,不論是安裝仍是刪除都很是低效,並且在windows上常常會出現由於超過最大嵌套層級而沒法刪除的狀況,不過好在後來官方調整了架構,改成平鋪的結構,解決了這些問題。

不過現階段npm的包管理仍是很混亂,咱們常常會看到下面這張圖:

img

  • npm如今有不少重複的包,不少不維護的包,這給使用者形成了困擾
  • npm依賴繁多,好比我就僅僅想開發一個react的demo,結果發現要安裝上千個包

npm官方應該也意識到了,因此它們正在開發下一代包管理工具Tink,相信不久的未來就會和咱們見面,是否是很期待呢?

相關文章
相關標籤/搜索