Yarn vs npm:你需要知道的一切

原文鏈接:Yarn vs npm: Everything You Need to Know

Facebook、Google、Exponent 和 Tilde 聯合推出了一個新的 JS 包管理工具 — Yarn,正如官方文檔中寫的,Yarn 是為了彌補 npm 的一些缺陷而出現的:

  • npm 安裝包(packages)的速度不夠快,拉取的 packages 可能版本不同

  • npm 允許在安裝 packages 時執行代碼,這就埋下了安全隱患

  • 別慌,Yarn 沒想要完全替代 npm,它只是一個新的 CLI 工具,拉取的 packages 依然來自 npm 倉庫。倉庫本身不會變,所以獲取或者發布模塊的時候和原來一樣。

    那麼,是不是所有人都要儘快搭上 Yarn 的車呢?取決於你在使用 npm 時有沒有遇到不可忍受的痛點。接下來,我們將會對比 npm 和 Yarn,看完之後,相信你就有了答案。

    Yarn vs npm:特性差異

    第一眼看到 Yarn,估計會覺得和 npm 也太像了吧。不過進一步了解 Yarn 之後,我們會發現它的特別之處。

    yarn.lock 文件

    npm 和 Yarn 都是通過 package.json 記錄項目需要拉取的依賴模塊,不過在使用時,往往 package.json 中模塊的版本號不太會寫得非常確切,通常是定個版本範圍。這樣你就能自行選擇使用模塊的大版本或者小版本,也允許 npm 拉取模塊最新的修復了 bug 的版本。

    在理想的語義化版本世界中,新版是不會有顛覆舊版本的改變,然而現實並非如此。這就導致了使用 npm 拉取依賴時,即使用的是相同的 package.json,在不同的設備上拉到的 packages 版本不一,這就可能為項目引入 bug。

    為了防止拉取到不同的版本,Yarn 有一個鎖定文件 (lock file) 記錄了被確切安裝上的模塊的版本號。每次只要新增了一個模塊,Yarn 就會創建(或更新)yarn.lock 這個文件。這麼做就保證了,每一次拉取同一個項目依賴時,使用的都是一樣的模塊版本。

    npm 其實也有辦法實現處處使用相同版本的 packages,但需要開發者執行 npm shrinkwrap 命令。這個命令將會生成一個鎖定文件,在執行 npm install 的時候,該鎖定文件會先被讀取,和 Yarn 讀取 yarn.lock 文件一個道理。npm 和 Yarn 兩者的不同之處在於,Yarn 默認會生成這樣的鎖定文件,而 npm 要通過 shrinkwrap 命令生成 npm-shrinkwrap.json 文件,只有當這個文件存在的時候,packages 版本信息才會被記錄和更新。

    1. yarn.lock 文檔
    2. npm shrinkwrap 文檔

    並行安裝

    無論 npm 還是 Yarn 在執行包的安裝時,都會執行一系列任務。npm 是按照隊列執行每個 package,也就是說必須要等到當前 package 成功安裝之後,才能繼續後面的安裝。而 Yarn 是同步執行所有任務,提高了性能。

    通過拉取 express 依賴,我比較了 npm 和 Yarn 的效率,在沒有用任何鎖定文件(也就是沒有緩存)的前提下,一共安裝 42 個依賴:

    1. npm 耗時 9 秒

    2. Yarn 耗時 1.37 秒

    這耗時……我沒法相信自己的眼睛了,反覆嘗試幾次,得到的結果也差不多。於是我又試著安裝了有195個依賴的 gulp,這一次:

    1. npm 耗時 11 秒

    2. Yarn 耗時 7.81 秒

    看來 npm 和 Yarn 在安裝包的速度差異和要安裝的包個數強相關,不過不管怎麼樣,Yarn 都比 npm 要快。

    更簡潔的輸出

    npm 的輸出信息比較冗長。在執行 npm install <package> 的時候,命令行里會不斷地列印出所有被安裝上的依賴。相比之下,Yarn 簡潔太多:默認情況下,結合了 emoji (Windows 上 emoji 不可見)直觀且直接地列印出必要的信息,也提供了一些命令供開發者查詢額外的安裝信息。

    CLI 區別

    除了特性上的區別,相比於 npm 的命令,Yarn 命令有增有減還有一些更改。

    yarn global

    npm 的全局操作命令要加上 -g 或者 --global 參數,Yarn 的全局命令則需要加上 global。和 npm 類似,項目特定的依賴,就不需要全局安裝了。

    當執行 yarn add、yarn bin、yarn ls 和 yarn remove 時添加 global 前綴才是有全局作用。除了 yarn add 之外,其他三個命令和 npm 的一樣。

    1. yarn global 文檔

    yarn install

    npm install 命令安裝的是 package.json 中的依賴,如果開發者在 package.json 中添加了新的依賴,npm install 也一樣安裝。然而,yarn install 會優先安裝 yarn.lock 中記錄的依賴,沒有這樣的鎖定文件時,才會去安裝 package.json 中的依賴。

    1. yarn install 文檔

    2. npm install 文檔

    yarn add [–dev]

    和 npm install 類似,yarn add 命令允許你添加並安裝依賴。通過這個命令添加的依賴都會被自動加到 package.json 中,和我們在 npm 命令中使用 --save 參數一樣。Yarn 的-dev 則等同於 npm 的 --save-dev。

    1. yarn add 文檔

    2. npm install 文檔

    yarn licenses [ls|generate-disclaimer]

    在寫這篇文章的時候,npm 沒有等同的命令。yarn licenses ls 用於羅列出所有被安裝的 package 所持有的執照情況。yarn licenses generate-disclaimer 將生成一個對所有依賴的免責聲明。有些執照要求開發者一定要在項目中包含這些它們,這個命令就是為這樣的場景存在的。

    1. yarn licenses 文檔

    yarn why

    這條命令能幫助開發者理清安裝的 package 之間的關係。拉取了各種依賴以後,有些 package 是你顯式安裝的,有些包則是遞歸依賴的。

    1. yarn why 文檔

    yarn upgrade [package]

    這條命令將根據 package.json 將 package 升級到最新版本,並更新 yarn.lock,和 npm update 相似。

    有意思的是,如果指定了 [package] 參數,Yarn 會將 package 升級到最新版本,並更新 package.json 中該 package 的版本號欄位。

    1. yarn upgrade 文檔

    yarn generate-lock-entry

    這條命令將會生成一份基於 package.json 的 yarn.lock 文件,作用和 npm shrinkwrap 類似。不過由於執行 yarn add andyarn upgrade 時都會更新 yarn.lock 文件,所以要慎重執行 yarn generate-lock-entry 命令

    1. yarn generate-lock-entry 文檔

    2. npm shrinkwrap 文檔

    穩定性和可依賴度

    看到 Yarn 剛發布時長長的 issue 列表,真的很擔心上了一輛靈車…但大家也可以看到問題解決的速度之快,令人震驚。可以感受到 Yarn 社區確實在攻克 bug,從問題列表上也能發現 Yarn 大部分 bug 發生在邊界情況下,其實對於大多數開發者而言,Yarn 已經足夠穩定了。

    雖然現在包管理工具在一個項目中扮演著不可或缺的角色,但它僅僅是個包管理工具。如果拉取的依賴出了問題,大可以重新拉取或者乾脆用 npm 再安裝看看。

    未來

    可能你想到了 Node.js 和 io.js 的愛恨情仇:io.js 源自 Node.js 的一個分支,它的領導者是原來 Node.js 的一些核心開發者,幾位核心開發者和 Node.js 的管理者產生了一些分歧,所以開啟了一個新的分支,不同於 Node.js,io.js 採用的是開放管理。不過一年不到,io.js 又合併回 Node.js 中,開發者們也不再更新 io.js。不去評論 io.js 的出走是對是錯,我們知道的是現在 Node.js 有了更多非常好的特性。

    在 npm 和 Yarn 上我看到了當初 Node 和 io 的影子,雖然 Yarn 之於 npm 並不是分支之於主幹的關係,但它確實彌補了 npm 的一些缺陷。如果 npm 能邀請 Facebook、Google 以及其他的 Yarn 社區推動者一同來改進 npm 不是很好嗎?雖然現在提這個為時尚早,但我真心希望 npm 能這麼做。

    現在看起來,Yarn 的未來一片光明。開發者們很期待這個新工具,也認可它作為一個包管理工具的能力。不過 Yarn 發展方向並沒有很明確,我也不確定將會有什麼新的特性。

    結論

    目前看來 Yarn 要比 npm 更好用:默認就有鎖定文件、更快速地安裝依賴以及依賴的更新會自動同步到 package.json 文件中。從 npm 遷移到 Yarn 成本幾乎為零,你大可以在一個項目里用用看,感受下它是否適合你。以上優點都讓 Yarn 成為了目前 npm 最好的替代品。

    我非常鼓勵大家儘快在項目中用起 Yarn。不過如果你是一個對新工具相當謹慎的人,也可以等多兩三個月再去嘗試。畢竟 npm 才是久經沙場的老將。

    如果你發現自己花費在等待 npm 安裝依賴上的時間實在太久了,那是時候試試看 Yarn 了,不如先從遷移文檔開始吧。

    你對 Yarn 怎麼看的?是不是已經用起了 Yarn?還是尚未使用但已經想試試看了?又或者覺得 Yarn 只是歷史進程中的一步?在這篇文章下留言吧,讓我們一起來討論 Yarn。

    附:一份很有用的 yarn 命令 cheat sheet

    推薦閱讀:

    如何用 Vue.js 實現一個建站應用
    已放棄了遊戲開發,不知道選擇什麼開發?

    TAG:前端开发 | npm | 模块 |