从 npm 迁移至yarn
?
NPM
?
npm是Node.js能夠如此成功的主要原因之一。npm團隊做了很多的工作,以確保npm保持向后兼容,并在不同的環境中保持一致。
npm是圍繞著語義版本控制(semver)的思想而設計的,下面是從他們的網站摘抄過來的:
給定一個版本號:主版本號.次版本號.補丁版本號, 以下這三種情況需要增加相應的版本號:
- 主版本號: 當API發生改變,并與之前的版本不兼容的時候
- 次版本號: 當增加了功能,但是向后兼容的時候
- 補丁版本號: 當做了向后兼容的缺陷修復的時候
npm使用一個名為package.json的文件,用戶可以通過npm install --save命令把項目里所有的依賴項保存在這個文件里。
例如,運行npm install --save lodash會將以下幾行添加到package.json文件中。
"dependencies": {"lodash": "^4.17.4" }請注意,在版本號lodash之前有個^字符。這個字符告訴npm,安裝主版本等于4的任意一個版本即可。所以如果我現在運行npm進行安裝,npm將安裝lodash的主版本為4的最新版,可能是 lodash@4.25.5(@是npm約定用來確定包名的指定版本的)。你可以在此處查看所有支持的字符:https://docs.npmjs.com/misc/semver。
理論上,次版本號的變化并不會影響向后兼容性。因此,安裝最新版的依賴庫應該是能正常工作的,而且能引入自4.17.4版本以后的重要錯誤和安全方面的修復。
但是,另一方面,即使不同的開發人員使用了相同的package.json文件,在他們自己的機器上也可能會安裝同一個庫的不同種版本,這樣就會存在潛在的難以調試的錯誤和“在我的電腦上…”的情形。
大多數npm庫都嚴重依賴于其他npm庫,這會導致嵌套依賴關系,并增加無法匹配相應版本的幾率。
雖然可以通過npm config set save-exact true命令關閉在版本號前面使用^的默認行為,但這個只會影響頂級依賴關系。由于每個依賴的庫都有自己的package.json文件,而在它們自己的依賴關系前面可能會有^符號,所以無法通過package.json文件為嵌套依賴的內容提供保證。
為了解決這個問題,npm提供了shrinkwrap命令。此命令將生成一個npm-shrinkwrap.json文件,為所有庫和所有嵌套依賴的庫記錄確切的版本。
然而,即使存在npm-shrinkwrap.json這個文件,npm也只會鎖定庫的版本,而不是庫的內容。即便npm現在也能阻止用戶多次重復發布庫的同一版本,但是npm管理員仍然具有強制更新某些庫的權力。
這是引用自shrinkwrap文檔的內容:
如果你希望鎖定包中的特定字節,比如是為了保證能正確地重新部署或構建,那么你應該在源代碼控制中檢查依賴關系,或者采取一些其他的機制來校驗內容,而不是靠校驗版本。
npm 2會安裝每一個包所依賴的所有依賴項。如果我們有這么一個項目,它依賴項目A,項目A依賴項目B,項目B依賴項目C,那么依賴樹將如下所示:
node_modules - package-A -- node_modules --- package-B ----- node_modules ------ package-C -------- some-really-really-really-long-file-name-in-package-c.js這個結構可能會很長。這對于基于Unix的操作系統來說只不過是一個小煩惱,但對于Windows來說卻是個破壞性的東西,因為有很多程序無法處理超過260個字符的文件路徑名。
npm 3采用了扁平依賴關系樹來解決這個問題,所以我們的3個項目結構現在看起來如下所示:
node_modules - package-A - package-B - package-C -- some-file-name-in-package-c.js這樣,一個原來很長的文件路徑名就從./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 3依賴解析的工作原理。
這種方法的缺點是,npm必須首先遍歷所有的項目依賴關系,然后再決定如何生成扁平的node_modules目錄結構。npm必須為所有使用到的模塊構建一個完整的依賴關系樹,這是一個耗時的操作,是npm安裝速度慢的一個很重要的原因。
由于我沒有詳細了解npm的變化,所以我想當然的以為每次運行npm install命令時,NPM都得從互聯網上下載所有內容。
但是,我錯了,npm是有本地緩存的,它保存了已經下載的每個版本的壓縮包。本地緩存的內容可以通過npm cache ls命令進行查看。本地緩存的設計有助于減少安裝時間。
總而言之,npm是一個成熟、穩定、并且有趣的包管理器。
Yarn
Yarn發布于2016年10月,并在Github上迅速擁有了2.4萬個Star。而npm只有1.2萬個Star。這個項目由一些高級開發人員維護,包括了Sebastian McKenzie(Babel.js)和Yehuda Katz(Ember.js、Rust、Bundler等)。
從我搜集到的情況來看,Yarn一開始的主要目標是解決上一節中描述的由于語義版本控制而導致的npm安裝的不確定性問題。雖然可以使用npm shrinkwrap來實現可預測的依賴關系樹,但它并不是默認選項,而是取決于所有的開發人員知道并且啟用這個選項。
Yarn采取了不同的做法。每個yarn安裝都會生成一個類似于npm-shrinkwrap.json的yarn.lock文件,而且它是默認創建的。除了常規信息之外,yarn.lock文件還包含要安裝的內容的校驗和,以確保使用的庫的版本相同。
由于yarn是嶄新的經過重新設計的npm客戶端,它能讓開發人員并行化處理所有必須的操作,并添加了一些其他改進,這使得運行速度得到了顯著的提升,整個安裝時間也變得更少。我估計,速度提升是yarn受歡迎的主要原因。
像npm一樣,yarn使用本地緩存。與npm不同的是,yarn無需互聯網連接就能安裝本地緩存的依賴項,它提供了離線模式。這個功能在2012年的npm項目中就被提出來過,但一直沒有實現。
yarn還提供了一些其他改進,例如,它允許合并項目中使用到的所有的包的許可證,這一點讓人很高興。
一個有趣的事情是,yarn文檔的態度開始針對npm發生改變,因為yarn項目變得流行起來。
最開始的yarn公告是這么介紹yarn的安裝的:
*最簡單的入門方法是運行:?
npm install -g yarn?
yarn*
現在的yarn安裝頁面是這么說的:
注意:通常情況下不建議通過npm進行安裝。npm安裝是非確定性的,程序包沒有簽名,并且npm除了做了基本的SHA1哈希之外不執行任何完整性檢查,這給安裝系統程序帶來了安全風險。
基于這些原因,強烈建議你通過最適合于你的操作系統的安裝方法來安裝yarn。
以這種速度發展下去的話,如果yarn要宣布他們自己的registry,讓開發者慢慢淘汰npm的話,我們一點都不會感到驚訝。
看起來似乎要感謝yarn,npm終于意識到他們需要更加關注一些大家強烈要求的問題了。當我在審核我之前提到的強烈要求的“離線”功能時,我注意到這個需求正在被積極地修復之中。
對多數用戶來說,從npm遷移的過程應該非常簡單。Yarn和npm使用相同的package.json格式,而且Yarn可以從npm安裝依賴包。
如果你打算在現有項目中嘗試Yarn,只需執行:
yarnYarn將通過自己的解析算法來重新組織node_modules?目錄,這個算法和node.js 模塊解析算法是兼容的。
如果出錯,請查閱issue列表,或者向Yarn issue tracker報告。
執行yarn命令或者yarn add <package>命令后,Yarn都會在項目根目錄下生成yarn.lock文件。 你無需理解此文件的具體內容,但請記得將其提交到代碼管理系統。 當其他開發者也從npm遷移到Yarn時,yarn.lock文件的存在會確保他們得到的依賴包與你的完全相同。
多數情況下,第一次執行yarn或者yarn add都會成功。 有些情況下,package.json文件里的信息不足以找出冗余依賴,Yarn安裝依賴時采用的確定性算法就會導致依賴沖突。 這種情況常常出現在那些由于npm install執行出現問題,node_modules文件夾被多次刪除,并重新安裝的大型項目里。 如果發生這種情況,請在遷移到Yarn前嘗試使用npm命令來讓依賴的版本更明確。
項目的其他開發者可以繼續使用npm,所以無需讓每個人同時遷移。 使用yarn會讓開發者得到完全相同的配置,而使用npm卻未必,但這是npm的預期行為。
如果你之后發現Yarn并不適合自己,你無需任何特別修改就能遷移回npm。 如果項目里所有人都不再使用Yarn,就可以刪除yarn.lock文件(但不是必須)。
如果項目目前使用了npm-shrinkwrap.json文件,請小心你可能會得到一組不同的依賴。 Yarn不支持npm shrinkwrap文件,因為文件里沒有足夠的信息來支撐Yarn的確定性算法。 所以如果項目正在使用 shrinkwrap 文件,那么團隊成員同時遷移到Yarn可能會更容易一點。 只需刪除現有的npm-shrinkwrap.json文件,并提交新創建的yarn.lock文件。
CLI 命令比較
| npm install | yarn install |
| (不適用) | yarn install --flat |
| (不適用) | yarn install --har |
| npm install --no-package-lock | yarn install --no-lockfile |
| (不適用) | yarn install --pure-lockfile |
| npm install [package] | yarn add [package] |
| npm install [package] --save-dev | yarn add [package] --dev |
| (不適用) | yarn add [package] --peer |
| npm install [package] --save-optional | yarn add [package] --optional |
| npm install [package] --save-exact | yarn add [package] --exact |
| (不適用) | yarn add [package] --tilde |
| npm install [package] --global | yarn global add [package] |
| npm update --global?? ? ? ? ? ? ? ? ? | yarn global upgrade?? ? ? ? ? ? ? ? ? ? |
| npm rebuild | yarn install --force |
| npm uninstall [package] | yarn remove [package] |
| npm cache clean | yarn cache clean [package] |
| rm -rf node_modules && npm install | yarn upgrade |
總結
以上是生活随笔為你收集整理的从 npm 迁移至yarn的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: golang orm 框架之 gorm
- 下一篇: 初探 React Router 4.0