first post on http://blog.xgheaven.com/2018/05/03/npm-to-yarn-to-npm/html
從接觸到 node 環境來講,其中一個不可或缺的一部分即是 npm 包管理,可是因爲官方的 npm 有各類各樣的問題,因而催生了不少不一樣的版本,這其中的曲折也許只有過來人才知道。node
在上古版本(應該是 npm3 之前的版本,具體我也記不清了),npm 的安裝策略並非扁平化的,也就是說好比你安裝一個 express
,那麼你會在 node_modules
下面只找到一個 express
的文件夾。而 express
依賴的項目都放在其文件夾下。linux
- app/
- package.json
- node_modules/
- express/
- index.js
- package.json
- node_modules/
- ...
複製代碼
這個帶來的問題或許 windows 用戶深諳其痛,由於在這種安裝環境下,會致使目錄的層級特別高,而對於 windows 來講,最大的路徑長度限制在 248 個字符(更多請見此),再加上 node_modules
這個單詞又特別長,因此你懂得,哈哈哈。解決方案啥的本身去搜索吧,反正估計如今也沒人會用上古版本了。git
除了 windows 用戶出現的問題之外,還有一個更嚴重的問題,就是模塊都是獨立的,好比說位於 express
下面的 path-to-regexp
和 connect
下面的 path-to-regexp
的模塊是兩個不一樣的模塊。 那麼這個會帶來什麼影響呢?其實在使用上,並無什麼太大的影響,可是內存佔用過大。由於不少相同模塊位於不一樣模塊下面就會致使有多個實例的出現(爲何會加載多個實例,請查看 Node 模塊加載)。你想一想,都是一樣的功能,爲何要實例這麼屢次呢?不能就加載一次,複用實例麼?github
上古時代的 npm 的缺點能夠說仍是不少的:express
後面,有人爲了解決目錄嵌套層次太高的問題,引入的軟連接的方案。npm
簡單來講,就是將全部的包都扁平化安裝到一個位置,而後經過軟連接(windows 快捷方式)的方式組合到 node_modules
中。json
- app/
- node_modules
- .modules/
- express@x.x.x/
- node_modules
- connect -> ../../connect@x.x.x
- path-to-regexp -> ../../path-to-regexp@x.x.x
- ... -> ../../package-name@x.x.x
- connect@x.x.x/
- path-to-regexp@x.x.x/
- ...others
- express -> ./.modules/express@x.x.x
複製代碼
這樣作的好處就是能夠將總體的邏輯層級簡化到不多的幾層。並且對於 node 的模塊解析來講,能夠很好的解決相同模塊不一樣位置致使的加載多個實例,進而致使內存佔用的狀況。windows
基於這種方案,有 npminstall 以及 pnpm 這個包實現了這種方案,其中 cnpm 使用的就是 npminstall,不過他們實現的方式和我上面講的是有差別的,具體請看。簡單來說,他們沒有 .modules
這一層。更多的內容,請看 npminstall 的 README。緩存
總的來說這種解決方案有還有如下幾個好處:
那麼缺點也是挺致命的:
最大的改變就是將目錄層級從嵌套變到扁平化,能夠說很好的解決了上面嵌套層級過深以及實例不共享的問題。可是,npm3 在扁平化方案下,選擇的並非軟鏈接的方式,而是說直接將全部模塊都安裝到 node_modules
下面。
- app/
- node_modules/
- express/
- connect/
- path-to-regexp/
- ...
複製代碼
若是出現了不一樣版本的依賴,好比說 package-a
依賴 package-c@0.x.x
的版本,而 package-b
依賴 package-c@1.x.x
版本,那麼解決方案仍是像以前的那種嵌套模式同樣。
- app/ - node_modules/ - package-a/ - package-c/ - // 0.x.x - package-b/ - node_modules/ - package-c/ - // 1.x.x 複製代碼
至於那個版本在外面,那個版本在裏面,彷佛是根據安裝的前後順序有關的,具體的我就不驗證了。若是有人知道的話,歡迎告訴我。
在這個版本以後,解決了大部分問題,能夠說 npm 跨入了一個新的世界。可是還要一個問題就是,他的安裝速度依舊很慢,相比 cnpm 來講。因此他還有不少進步的空間。
隨着 Node 社區的愈來愈大,也有愈來愈多的人將 Node 應用到企業級項目。這也讓 npm 暴露出不少問題:
因此,此時 yarn 誕生了,爲的就是解決上面幾個問題。
那個時候我還在使用 cnpm,我特意比較了一下,發現仍是 cnpm 比較快,因而我仍是繼續使用着 cnpm,由於對於我來講足夠了。可是後面發現 yarn 真的愈來愈火,再加上 cnpm 長久不更新。我也嘗試着去了用 yarn,在嘗試以後,我完全放棄了 cnpm。並且直到如今,彷佛尚未加入 lock 的功能。
固然 yarn 還不僅只有這麼幾個好處,在用戶使用方面:
yarn global
下面都是與全局模塊相關的命令。並且提示很是徹底,一眼就能看明白是什麼意思。不會像 npm 同樣,npm --help
就是一坨字符串,還不講解一下是什麼用處,看着頭疼。-S
參數node_modules/.bin
下的可執行文件。這個是我用 yarn 最高的頻率。好比你安裝了 yarn add mocha
,而後就能夠經過 yarn run mocha
直接運行 mocha
。而不須要 ./node_modules/.bin/mocha
運行。是我最喜歡的一個功能npm outdated
看看那些包須要更新,而後經過 npm update [packages]
更新指定的包。而在 yarn 當中,能夠經過交互式的方式,來選擇那些須要更新,那些不須要。/usr/lib/node_modules
下面安裝,而後經過軟鏈接鏈接到 /usr/local/bin
目錄下。而 yarn 的作法是選擇一個目錄,這個目錄就是全局模塊安裝的地方,而後將全部的全局模塊當作一個項目,從而進行管理。這個好處就是,你能夠直接備份這個目錄當中的 package.json 和 yarn.lock 文件,從而能夠很方便的在另外一個地方還原你安裝了那些全局模塊。至於這個目錄的問題,經過 yarn global dir
命令就能夠找到,mac 下是在 ~/.config/yarn/global/
,linux 我沒有測試過。能夠說 yarn 用起來很是舒服,可是惟一的缺點就是否是 npm 官方出的,更新力度、兼容性都會差一些。但這也阻擋不住 yarn 在 Node 社區的火熱程度。很快,你們紛紛從 npm 切換到 yarn 上面。
在受到 yarn 的衝擊以後,npm 官方也決定改進這幾個缺點,因而發佈了和 Yarn 對抗(這個詞是我意淫的)的 npm5 版本。
-S
參數至此,yarn 和 npm 的差距已經很是很是小了,更多的差距體如今用戶體驗層面,我使用 yarn 的功能也只剩下全局模塊管理、模塊交互式更新和 yarn run
這個命令了。
可是後面推出的 npx 讓我放棄了使用 yarn run
這個命令。不是說 npx 比 yarn 有多好,而是說 npm 集成了這個功能,也就不必再去使用第三方的工具了。並且 npx 還支持臨時安裝模塊,也就是那種只用一次的命令,用完就刪掉了。
後面我又發現了 npm-check
這個工具,我用它來替代了 yarn 的交互式更新。
然而 npm6 的出現加入了緩存,而且又進一步提高了速度,能夠說直逼 yarn。
因而 yarn 對我來講只剩下一個全局模塊管理的功能了。個人整個開發流程以及從 yarn 切換回 npm 上面了。或許後面的日子我也會讓 npm 來接管全局模塊管理,從而放棄使用 yarn。可是我仍是會裝 yarn,畢竟有一些老項目仍是用 yarn 的。
我經歷了從 npm -> cnpm -> yarn -> (npm + npm-check + npx) 的一個循環,也見證了 npm 社區的一步步發展。並且 yarn 的更新頻率也很是慢,可能一個月才更新一次,這也讓我逐漸放棄使用 yarn。
有的時候感受,第三方的終究是第三方,仍是沒有原生的好用和方便,並且用起來安心。