如何讓 YARN 支持 CNPM 的完整加速

國內的前端開發人或多或少都瞭解過 cnpm ,但項目開發因人而異,不少時候不會或不能使用 cnpm ,不可勝數的項目在使用 yarn 或者其餘包管理器安裝依賴。本文將介紹這樣的狀況下如何加速二進制文件下載。

在前一段時間發佈的 Github Octoverse 2019 報告中,JavaScript 繼續蟬聯最受歡迎編程語言。JavaScript 生態的保持繁榮,與 Node.js 的流行密不可分。而說到 JavaScript 生態,不得不提到 npm,npm 不只是前端開發首選的包管理器,也是除了 Github 以外最重要的代碼共享途徑。Snyk 2019 開源安整年報中指出,npm 生態的包數量遠超其餘包管理器。前端

各個包管理器生態的包總數

現階段,主流的前端開源項目在發佈時都會使用 npm 的在線託管服務 https://www.npmjs.com/。但開發者可以使用的包管理器卻不止 npm 一個,來自開源社區的 yarn 和 pnpm 正在被愈來愈多人使用,它們最顯著的優勢就是加快依賴的安裝速度。對於中國開發者,由阿里巴巴開源的 cnpm 也是一個重要的選擇。vue

關於 CNPM 的那些事

reactvue 引領的前端工程化開發在國內大規模流行以來,前端項目的依賴安裝成爲了平常工做的重要組成部分。cnpm 的出現解決了因爲網絡環境形成的安裝速度慢問題,受到了大量國內開發者的歡迎。node

cnpm 的誕生早於 yarn 和 pnpm ,它使用 npminstall 模塊執行安裝。由淘寶開發團隊維護的 npm 倉庫鏡像,會定時同步 npm 官方的全部模塊 。cnpm 無需任何配置就會默認從淘寶鏡像下載全部的包,從而達到國內加速的目的。具體的使用方式能夠查看官方文檔 https://npm.taobao.org/react

雖然目前 cnpm 的速度一如既往得快,但對比其餘競品它卻再也不像剛誕生時那樣有優點了,加上實際開發時莫名其妙的報錯也難以解決,還有各類各樣的其餘因素。愈來愈多的團隊又切換回了 npm ,或者轉而使用具有更多功能的 yarn 或 pnpm 。git

yarn 是 Facebook 團隊開源的包管理器,它能建立更扁平的依賴樹,只會安裝變動的模塊,使用並行下載,用本機緩存加速安裝。而 pnpm 做爲黑馬,其口碑甚至優於 yarn ,但因爲筆者沒有使用經驗,因此不會在本文中介紹它的使用方式。

我想確定有讀者想吐槽,爲何不用 cnpm ,非要折騰?但這並無具體的答案,每一個團隊,每一個人都有各自的狀況,無須妄加批評。終歸都是發現問題解決問題。接下來會介紹怎麼用最低限度的配置讓 yarn 也得到 cnpm 的國內加速能力。github

NPM 和 YARN 使用鏡像加速

這個部分不是什麼新鮮內容了,全部的包管理器均可以設置倉庫地址。具體的細節建議閱讀 npm 的官方文檔。npm

除了「衆所周知的命令行配置法」之外,也能夠在項目中建立 .npmrc 文件。若是將該文件一併提交到 Git 就能與全部環境共享該配置,利於多人協做,也能夠被 CI 和其餘第三方工具使用。所以也是筆者推薦使用的方法。編程

# .npmrc
registry = https://registry.npm.taobao.org

yarn 一樣也會讀取這個文件,除非你在 .yarnrc 中覆蓋了這一配置。json

# .yarnrc
registry "https://registry.npm.taobao.org"

配置二進制文件的鏡像地址

單純的使用國內 npm 鏡像並不能解決全部問題。最知名的例子:前端工程化

爲了簡化 CSS 的編寫,許多項目都會使用預處理器。在國內,預處理器less比生態更加完整的 sass 處理器流行的緣由之一,即是由於 sass 的編譯工具 node-sass 的安裝曾經十分困難,許多公司、團隊和我的開發者所以決定了選型使用 less

node-sass 之因此難以安裝,是它在 npm 安裝流程以後,還會觸發一個而外的編譯流程。其中使用了 C++ 編譯的二進制文件,該文件根據版本託管在 https://github.com/sass/node-... 。Github 使用了亞馬遜的 AWS 服務做爲 CDN,因爲某些衆所周知的緣由,在中國大陸有時會沒法訪問。因而乎在該文件下載失敗後,就會觸發本機編譯以生成替代的二進制文件,這一過程每每以失敗了結(尤爲是在 Windows 7 系統)。不少網絡教程這時候會建議安裝 C++ 相關的編譯環境,也有人會說 「用 Linux 保平安」。

但實際上只要能解決二進制文件的下載問題就能大大提升成功率。淘寶鏡像上也提供了相應的二進制包,經過設置環境變量使用國內加速。cnpm 內置了這一過程,因此能夠自動解決這一狀況。

不使用 cnpm 的話,則經過命令行設置環境變量:

# 全局配置,單臺設備上永久生效
yarn config set sass_binary_site https://npm.taobao.org/mirrors/node-sass/

# 針對單次安裝
SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/ && yarn add node-sass
# or
yarn add node-sass --sass_binary_site https://npm.taobao.org/mirrors/node-sass/

或者一樣將其配置在 .npmrc 文件中達到分享配置的效果:

# .npmrc
sass_binary_site = https://npm.taobao.org/mirrors/node-sass/
electron_mirror = https://npm.taobao.org/mirrors/electron/

phantomjselectron 等一樣可使用此方法加速,由於他們都容許使用環境變量設置鏡像 url。咱們能夠在 https://npm.taobao.org/mirrors 上查看全部可用的鏡像。

網絡上絕大多數的文章也就到此爲止了,然而這還不是所有。

使用 bin-wrapper-china

imagemin 是一系列基於 C++ 實現的圖片壓縮模塊,其中包含了 pngquantmozjpeg 等知名庫,和 node-sass 同樣須要下載二進制文件。然而它卻沒有不支持使用環境變量配置鏡像倉庫 url,自主編譯的成功率也要低得多。這時候不管是 npm 仍是 yarn 都只能聽天由命祈禱網絡暢通。

沒錯,cnpm 經過內置的處理也解決了這種狀況,那是否是要吃回頭草用 cnpm 呢?

固然不用,查看源碼能夠發現,至關一部分使用了二進制文件的模塊,都會經過 bin-wrapper 執行下載和編譯。因而乎只要能在下載以前將 bin-wrapper 內使用的下載連接替換成鏡像倉庫的 url,問題便迎刃而解。

筆者爲此建立了一個工具 bin-wrapper-china,該工具 fork 了原版的 bin-wrapper,並讀取了 cnpm 所使用的 binary-mirror-config 獲取全部可用的鏡像淘寶鏡像 url,替換下載文件的連接。這樣就能夠愉快地使用加速功能。那麼問題來了,怎樣用 bin-wrapper-china 代替 bin-wrapper 執行下載呢?

答案是使用 yarn 的殺手級功能 resolutions (npm 不支持),它容許咱們用 yarn 執行安裝時,用指定的模塊替換另外一個模塊,具體的配置方法以下:

// package.json with yarn
{
  "resolutions": {
    "bin-wrapper": "npm:bin-wrapper-china"
  }
}

bin-wrapper-china 的「冒名頂替」發生在安裝過程之中,bin-wrapper 的運行發生在安裝以後 ,因此可以無縫的運行。這樣一來 imagemin 系列的安裝成功率便能大爲提升,關於 resolutions 的相關說明,詳見:

對於支持環境變量的模塊,例如 node-sass 等,bin-wrapper-china 也能提供了 china-bin-env 命令代替手動環境變量的支持。但因爲咱們不建議注入 yarn 或 npm 自己,而環境變量的注入必須在安裝以前執行,故在有須要的狀況下在項目內手動設置 preinstall 命令:

// package.json
{
  "scripts": {
    // Use npm
    "preinstall": "npm install bin-wrapper-china -D && china-bin-env",
    // Use yarn
    "preinstall": "yarn add bin-wrapper-china -D && china-bin-env"
  }
}

基於 preinstall 的操做須要 bin-wrapper-china 的提早安裝,筆者也但願後續有更好的解決方案。

總結

因爲 cnpm 的一些功能缺失,咱們可能會決定棄用它,可是它的加速能力又是咱們所須要的。

總結起來,cnpm 作了三件事:

  • 使用淘寶 npm 鏡像倉庫加速常規模塊的安裝。
  • 可配置的二進制文件,提早注入環境變量進行加速。
  • 不可配置的二進制文件,強行替換 url 加速下載。

這也是咱們要作的三件事(一般配置在項目中):

  • 經過 .npmrc 文件配置 npm 倉庫地址爲國內鏡像地址。
  • 經過 .npmrc 文件配置環境變量,或經過 bin-wrapper-chinachina-bin-env 命令注入環境變量。
  • 配置 yarn resolutions, 用 bin-wrapper-china 冒充 bin-wrapper 實現 url 替換。

固然了,若是你下定決心使用 cnpm ,或者所處的工做網絡可以暢通無阻,或者項目不須要安裝含二進制文件的模塊(例如筆者在項目中用 sass 替換 node-sass),就不須要考慮這問題了。本文雖然推薦使用 yarn ,但其核心流程適用於大多數 Node.js 生態內的包管理器,各位讀者有興趣能夠作更多探索。

相關項目:

相關文章
相關標籤/搜索