Facebook開源了Yarn,這是針對存儲在npm或Bower注冊表中的JavaScript模塊的一個(gè)代理包管理器。
按照其三位工程師所撰寫的博客文章,多年以來,F(xiàn)acebook一直非常成功地使用npm客戶端。在他們的團(tuán)隊(duì)中,這起初運(yùn)行得很不錯(cuò),直到代碼庫增長到一個(gè)點(diǎn),此時(shí)“一致性、安全性以及性能”方面的問題開始浮現(xiàn):
在Facebook,我們的很多項(xiàng)目,比如React,都會依賴npm注冊表中的代碼。但是,隨著內(nèi)部的擴(kuò)展,當(dāng)在不同的機(jī)器和用戶上安裝依賴時(shí),我們遇到了一致性的問題,還要考慮到加載依賴所消耗的時(shí)間,另外,npm客戶端在加載某些依賴的時(shí)候,會自動(dòng)執(zhí)行代碼,這也會帶來安全方面的問題。
例如,更新babel的一個(gè)小版本都會導(dǎo)致800,000行的提交,這樣的話,對于非法utf8字節(jié)序列、Windows換行符以及non png-crushed圖片觸發(fā)lint規(guī)則校驗(yàn)就會非常困難。對node_modules合并變更經(jīng)常會耗費(fèi)工程師一整天的時(shí)間。
他們所做的最后一次嘗試就是從源碼中移除這些模塊,并將其放到內(nèi)部的CDN上。但是,這意味著要為開發(fā)和CI構(gòu)建機(jī)器提供互聯(lián)網(wǎng)的連接,而這是無法接受的。最終,他們構(gòu)建了自己的包管理器,名為Yarn,F(xiàn)acebook認(rèn)為它是快速、可靠和安全的。
Yarn具有多項(xiàng)特性:
離線模式(Offline Mode):如果你之前安裝過某個(gè)包,那么你可以在沒有互聯(lián)網(wǎng)連接的情況下,對這個(gè)包進(jìn)行重新安裝。確定性(Deterministic):不管安裝順序如何,相同的依賴在每臺機(jī)器上會以完全相同的方式進(jìn)行安裝。網(wǎng)絡(luò)性能:Yarn會對請求進(jìn)行高效地排隊(duì),避免出現(xiàn)請求瀑布(waterfall),便于將網(wǎng)絡(luò)的使用效率達(dá)到最大化。網(wǎng)絡(luò)彈性(Network Resilience):單個(gè)請求的失敗不會導(dǎo)致整個(gè)安裝的失敗,請求會基于故障進(jìn)行重試。扁平模式(Flat Mode):將不匹配的依賴版本都會解析為同一個(gè)版本,避免重復(fù)創(chuàng)建。另外值得一提的特性就是Yarn能夠與npm和Bower注冊表協(xié)作使用。
經(jīng)營npm注冊表的npm公司對 Yarn表示歡迎,因?yàn)檫@是對已有Node.js管理器的一個(gè)補(bǔ)充,值得注意的是,盡管Yarn會從registry.yarnpkg.com抓取包,但這個(gè)倉庫僅僅是官方npm注冊表的一個(gè)代理。還有Facebook沒有明確提及的一點(diǎn),Yarn的另外一個(gè)目的在于:在npm注冊表宕機(jī)時(shí),所有的Node模塊能有一個(gè)安全的備份,因?yàn)樵诮衲甏禾靚pm曾經(jīng)停機(jī)2.5小時(shí),導(dǎo)致世界范圍內(nèi)成千上萬的開發(fā)人員構(gòu)建失敗。除非具有像Facebook那樣的擴(kuò)展性和開發(fā)需求,Yarn不一定是必須的,但是通過代理來獲取包能夠在原始注冊表發(fā)生宕機(jī)時(shí),提供一個(gè)彈性層。
Facebook還介紹說Yarn是與Exponent、Google和Tilde協(xié)作的成果。它的代碼已經(jīng)基于BSD許可證協(xié)議在GitHub上開源。