【Web技術】334- yarn、npm、cnpm 三者如何優雅的在一塊兒使用 ?

前端得包管理你有過幾個?前端

640?wx_fmt=jpeg

一位用很差包管理器的前端,是一個入門級前端,一個用很差webpack的前端,是一個初級前端node

三個包管理器是能夠一塊兒用的,只要你夠膽大心細,就沒任何問題!webpack

javeScript編寫中, 咱們儘可能不要定義全局變量,封裝函數儘可能不要有反作用, 由於所有變量的查詢時間會比局部變量的查詢慢, 更是考慮在 Node 的環境中沒法被垃圾回收的問題程序員

老規矩 先看原理

npm

  • npm 是 Node.js 可以如此成功的主要緣由之一。npm 團隊作了不少的工做,以確保 npm 保持向後兼容,並在不一樣的環境中保持一致。web

  • npm 是圍繞着 語義版本控制(semver)的思想而設計。算法

  • 給定一個版本號:主版本號. 次版本號. 補丁版本號, 如下這三種狀況須要增長相應的版本號:npm

  • 主版本號:當 API 發生改變,並與以前的版本不兼容的時候json

  • 次版本號:當增長了功能,可是向後兼容的時候segmentfault

  • 補丁版本號:當作了向後兼容的缺陷修復的時候設計模式

  • npm 2 會安裝每個包所依賴的全部依賴項。若是咱們有這麼一個項目,它依賴項目 A,項目 A 依賴項目 B,項目 B 依賴項目 C,那麼依賴樹將以下所示:

640?wx_fmt=png
  • 這個結構可能會很長。這對於基於 Unix 的操做系統來講只不過是一個小煩惱,但對於 Windows 來講倒是個破壞性的東西,由於有不少程序沒法處理超過 260 個字符的文件路徑名。

  • npm 3採用了扁平依賴關係樹來解決這個問題,因此咱們的 3 個項目結構如今看起來以下所示:

存了已經下載的每一個版本的壓縮包。本地緩存的內容能夠經過 npm cache ls 命令進行查看。本地緩存的設計有助於減小安裝時間。

640?wx_fmt=png
  • 這樣,一個原來很長的文件路徑名就從./node_modules/package-A/node_modules/package-B/node-modules/some-file-name-in-package-c.js變成了/node_modules/some-file-name-in-package-c.js

  • 這種方法的缺點是,npm必須首先遍歷全部的項目依賴關係,而後再決定如何生成扁平的 node_modules 目錄結構。npm 必須爲全部使用到的模塊構建一個完整的依賴關係樹,這是一個耗時的操做,是 npm 安裝速度慢的一個很重要的緣由。

  • 想固然的覺得每次運行npm install命令時,NPM都得從互聯網上下載全部內容。

  • 可是,npm是有本地緩存的,它保存了已經下載的每一個版本的壓縮包。本地緩存的內容能夠經過npm cache ls命令進行查看。本地緩存的設計有助於減小安裝時間。

cnpm

  • cnpmnpm用法徹底一致,只是在執行命令時將npm改成cnpm

  • npm安裝插件是從國外服務器下載,受網絡影響大,可能出現異常,若是 npm 的服務器在中國就行了,因而淘寶團隊幹了這事。來自官網:「這是一個完整 npmjs.org 鏡像,你能夠用此代替官方版本 (只讀),同步頻率目前爲 10 分鐘 一次以保證儘可能與官方服務同步。

  • 官方地址:http://npm.taobao.org

  • 安裝: npm install -g cnpm --registry=https://registry.npm.taobao.org

Yarn

  • Yarn一開始的主要目標是解決上一節中描述的因爲語義版本控制而致使的 npm 安裝的不肯定性問題。雖然可使用npm shrinkwrap來實現可預測的依賴關係樹,但它並非默認選項,而是取決於全部的開發人員知道而且啓用這個選項。

  • Yarn採起了不一樣的作法。每一個 yarn 安裝都會生成一個相似於 npm-shrinkwrap.json 的 yarn.lock 文件,並且它是默認建立的。除了常規信息以外,yarn.lock文件還包含要安裝的內容的校驗和,以確保使用的庫的版本相同。

  • yarn 是通過從新設計的嶄新的 npm 客戶端,它能讓開發人員並行處理全部必須的操做,並添加了一些其餘改進。

  • 運行速度獲得了顯著的提高,整個安裝時間也變得更少

  • 像 npm 同樣,yarn 使用本地緩存。`與npm不一樣的是,yarn無需互聯網鏈接就能安裝本地緩存的依賴項,它提供了離線模式`

  • 容許合併項目中使用到的全部的包的許可證

  • 一般狀況下不建議經過 npm 進行安裝。npm 安裝是非肯定性的,程序包沒有簽名,而且 npm 除了作了基本的 SHA1 哈希以外不執行任何完整性檢查,這給安裝系統程序帶來了安全風險。(做者曾經在一個上百個依賴包的項目中使用npm丟包過,代價很是大,淚水不自覺掉下來)

首先看一次很是失敗的包下載 居然是從全局讀取的資源 (不配置webpack別名是由於就這一個路徑這麼長)

640?wx_fmt=png

首先咱們從原理入手 ,咱們使用 npm inityarn init ,cnpm init 的時候 發生了什麼 ?

  • 生成package.json文件

  • json文件內部聲明初始的版本信息、做者信息等,若是你是須要上傳到 npm 上做爲命令行工具,應該配置bin等聲明入口字段

那麼當咱們使用npm i , yarn add ,cnpm i 操做時候會發生什麼 ?

  • 首先會根據你的命令行後綴是否加了 -g 或者global判斷,下載的包是放在全局的環境,仍是當前package.json文件對應的node_module文件夾目錄下 (這點尤爲重要,有人出 BUG,就是由於在用npm , cnpm時候沒有註明添加的是全局依賴仍是本地依賴,致使json文件上沒有對應的包名,項目永遠起不來)

  • 而後根據你的指令--save 或者-D--save -dev判斷是開發依賴仍是線上依賴,其實這點在yarn上沒有問題,由於yarn有本身的一套檢查包完整性的機制,不會丟包,還會自動判斷添加依賴,出bug通常是cnpmnpm,沒有明確-g或者--savenpm只有檢查程序員簽名的機制,沒有檢查包完整性的機制,也不會自動添加依賴到json文件,那麼就會出現丟包的假象,因此建議主要使用`yarn`

yarn 和 npm 對比

640?wx_fmt=png

npm 的缺點彙總:

  • 同一個項目,安裝的時候沒法保持一致性。因爲 package.json 文件中版本號的特色,下面三個版本號在安裝的時候表明不一樣的含義。

    "5.0.3",
    "~5.0.3",
    "^5.0.3"
  • 「5.0.3」 表示安裝指定的 5.0.3 版本,「~5.0.3」 表示安裝 5.0.X 中最新的版本,「^5.0.3」 表示安裝 5.X.X 中最新的版本。這就麻煩了,經常會出現同一個項目,有的同事是 OK 的,有的同事會因爲安裝的版本不一致出現bug

  • 安裝的時候,包會在同一時間下載和安裝,中途某個時候,一個包拋出了一個錯誤,可是 npm 會繼續下載和安裝包。由於 npm 會把全部的日誌輸出到終端,有關錯誤包的錯誤信息就會在一大堆npm打印的警告中丟失掉,而且你甚至永遠不會注意到實際發生的錯誤。

`yarn`的優勢

  • 速度快 。速度快主要來自如下兩個方面:

  • 並行安裝:不管 npm 仍是 Yarn 在執行包的安裝時,都會執行一系列任務。npm 是按照隊列執行每一個 package,也就是說必需要等到當前 package 安裝完成以後,才能繼續後面的安裝。而 Yarn 是並行執行全部任務,提升了性能。

離線模式:若是以前已經安裝過一個軟件包,用Yarn再次安裝時之間從緩存中獲取,就不用像npm那樣再從網絡下載了

  • 安裝版本統一:爲了防止拉取到不一樣的版本,Yarn 有一個鎖定文件 (lock file) 記錄了被確切安裝上的模塊的版本號。每次只要新增了一個模塊,Yarn 就會建立(或更新)yarn.lock 這個文件。這麼作就保證了,每一次拉取同一個項目依賴時,使用的都是同樣的模塊版本。npm 其實也有辦法實現到處使用相同版本的 packages,但須要開發者執行 npm shrinkwrap 命令。這個命令將會生成一個鎖定文件,在執行 npm install 的時候,該鎖定文件會先被讀取,和 Yarn 讀取 yarn.lock 文件一個道理。npm 和 Yarn 二者的不一樣之處在於,Yarn 默認會生成這樣的鎖定文件,而 npm 要經過 shrinkwrap 命令生成 npm-shrinkwrap.json 文件,只有當這個文件存在的時候,packages 版本信息纔會被記錄和更新。

  • 更簡潔的輸出:npm 的輸出信息比較冗長。在執行 npm install 的時候,命令行裏會不斷地打印出全部被安裝上的依賴。相比之下,Yarn 簡潔太多:默認狀況下,結合了 emoji直觀且直接地打印出必要的信息,也提供了一些命令供開發者查詢額外的安裝信息。

  • 多註冊來源處理:全部的依賴包,無論他被不一樣的庫間接關聯引用多少次,安裝這個包時,只會從一個註冊來源去裝,要麼是 npm 要麼是 bower, 防止出現混亂不一致。

  • 更好的語義化: yarn改變了一些npm命令的名稱,好比 yarn add/remove,感受上比 npm 本來的 install/uninstall 要更清晰。

那不是標題黨? 說了yarn這麼多優勢,咱們爲何還要npm呢?

你不用npm publish ,你怎麼上傳包到npm? 你不用cnpm,是下載不了一些包的

搞清楚三者下載包(依賴)的本質結果:

  • 首先向對應的node_module文件夾下面下載包(若是你非要下到全局,那麼再見)

  • 再而後是json文件中添加對應的依賴字段, 肯定是線上依賴仍是開發依賴

  • 只要作到這二者 你就下包成功

  • 總結就是 只要結果 過程管你是啥

使用yarn下載過的包,再使用npm cnpm下載 會重複下載,刪除以前的包

  • puppeteer這個包所依賴的mini版谷歌瀏覽器使用cnpm下載就能夠完美解決

  • prerender-spa-plugin這個包依賴上面的木偶戲 puppeteer這個包,也能夠用cnpm下載

  • 混合使用包管理器切記,不要重複下載依賴,npm cnpm下載依賴,必定要添加註明是什麼依賴,是否全局安

  • yarnnpm i二者,選擇前者,緣由在上面有提到,整體來講,yarn是不二選擇,可是其餘二者也不可缺乏,好比electron這個依賴,使用cnpm就能夠完美一鍵安裝

只要膽大心細,就能夠把三者用得如魚得水,否則就會被按在地上摩擦,實踐過程踩坑也是正常 以爲寫得好別忘了關注個人專欄,給個贊再走~

原文做者:Peter譚金傑

地址:https://segmentfault.com/a/1190000019299845


原創系列推薦

1. JavaScript 重溫系列(22篇全)

2. ECMAScript 重溫系列(10篇全)

3. JavaScript設計模式 重溫系列(9篇全)

4. 正則 / 框架 / 算法等 重溫系列(16篇全)

5. Webpack4 入門手冊(共 18 章)(上)

6. Webpack4 入門手冊(共 18 章)(下)

7. 59篇原創系列彙總 

640?wx_fmt=png

640?wx_fmt=png

點這,與你們一塊兒分享本文吧

相關文章
相關標籤/搜索