NPM 7:這才算是真正的更新

2020-12-11 InfoQ技術實驗室

備受我們信賴的 NPM 上一次迎來重大更新後已經過了一段時間了。終於,在 Node 的最新版本(版本 15)中,我們等到了 NPM 的版本 7。這一版本對其內部架構進行了重大改進,並提供了一些非常有趣的新特性。

在本文中,我會介紹兩個引起我注意並激發我的想像力的新特性。第一個特性會改變我們處理所有項目依賴項的方式,而第二個特性會優化一個之前必須手動完成的流程。

當然,我指的就是 工作區(workspaces)和自動安裝 對等依賴項(peer dependencies) 的能力。是不是來興趣了?反正我心情很激動!

工作區

我最近分享了一篇文章,其中介紹了兩種 NPM 客戶端,它們都想要解決官方客戶端當前實現中的一個主要問題:npm_modules 文件夾已經成為了一個磁碟空間黑洞。

https://blog.bitsrc.io/npm-clients-that-are-better-than-the-original-cd54ed0f5fe7

這兩種選項都有自己的獨特解決方案,但總體來說它們都會將所有模塊保存在一個共享文件夾中,讓各個項目之間能夠更容易共享軟體包。而隨著 NPM 最新版本的發布和 Arborist 的引入(一個新項目,包含了負責遍歷和分析 npm_modules 文件夾內模塊目錄樹的邏輯),我們看到了官方對這種方法的回應:工作區

請注意,這並不是一個全新的概念,其他包管理器(例如 Yarn 和 pnpm)已經有了自己的工作區實現。因此,你可以說這只是官方的一個工作區版本而已。

這是什麼?

你可以將它視為在預定義和通用上下文內的項目之間共享軟體包的一種方式。這並不是說軟體包是完全通用的,或者所有內容都要放進同一個下載位置。這個方案確實可以解決一遍又一遍地複製模塊的麻煩,還能讓你控制我們的模塊要共享給哪些項目。

創建工作區後,你就可以明確地告訴 NPM,你的程序包將存放在何處。並且由於新版客戶端可以感知工作區,因此它會正確安裝依賴項,而不會複製那些通用的依賴。

使用其他包管理器時這個功能也非常有用。例如,可以在單個 NPM 工作區中管理的多個項目之間共享一個 Bit 組件。修改共享組件時,可以用工作區從多個項目中獲得即時反饋(查看是否有哪裡出現了中斷)。

它向後兼容嗎?

可惜不行!工作區不是區區配置更改那麼簡單,它還要求你用新的方式來構造項目。因此向後兼容是做不到的,你不能運行一條 npm 命令就一次性規範化 10 個項目。但是,你可以在重新考慮所有這些項目的結構並正確更改配置之後,將這些項目的依賴項重新安裝到一個位置裡,這樣就可以對所有內容執行重複數據刪除操作了。在我看來,這確實是一項巨大的進步!

這個新特性會強制你考慮工作區的實際結構,以及不同項目之間的相互關係,這還會幫助你改善項目的內部組織架構。

考慮下面的例子

有很多介紹工作區的文章,但它們提供的示例在我看來沒什麼用,所以這裡我舉一個例子,希望能對 Node.js 開發人員更有幫助。

考慮以下文件夾結構:

基本上,我們將要處理一組 REST API,其中每個 API 的實際代碼都會放在「apis」工作區內,而通用代碼和共享包將在「core」工作區。

我們如何做到這一點呢?了解了它的工作原理後,配置過程實際上非常簡單。這裡的重點是你需要在聲明工作區的根級別(在 REST-APIS 文件夾內)定義一個 package.json 文件。準備好之後,你要做的就是在每個項目中都創建一個 package.json,並在其中聲明其所需的依賴項。

然後,你從根文件夾運行 npm install,讓 NPM 完成剩餘的工作。下面是根文件夾中的 package.json 文件:

你要做的只有這些,你當然可以定義其他屬性,但是對於這個新特性來說,「workspaces」鍵就足夠了。在其中,你可以定義(如示例所示)一個路徑列表(還有包含的通配符格式),這些路徑引用了工作區所在的文件夾。

在這些文件夾中,你只需聲明自己的 package.json 文件,而每個文件都聲明它自己的依賴項。

你可以看到,各個 API 文件夾的 JSON 文件實際上區別只有名稱和依賴項。core 文件夾也是如此,我們在其中將 Express 聲明為其主要共享依賴項:

現在,我們可以從根文件夾運行 npm install,你覺得會發生什麼呢?它將在一個通用的 node_modules 文件夾中安裝所有這些工作區所需的所有內容。因此,重複的依賴項不會佔用多份空間。

有了這些命令和文件夾結構後,你在根目錄級別的 node_modules 文件夾中安裝了所有三個模塊(及其必需的依賴項)。但是,其層次結構內的任何文件都能訪問所有這三個文件。

看看 apis/api2/ 文件夾中的這個文件:

const express = require('express')const app = express()const port = 3000const winston = require("winston")const flat = require("flat")app.get('/', (req, res) => { res.send('Hello World!')})app.listen(port, () => { console.log(`Example API (#2) listening at http://localhost:${port}`)})它用上了所有三個依賴項,而在以前它本來是找不到它們的,這太棒了!

你需要工作區嗎?

好吧,如果你正在處理的是單個項目,或者是一些互不相關的項目,那麼工作區可能對你來說並沒什麼用途。它們的需求可能會隨時改變,結果讓工作區帶來的好處煙消雲散。

但是,如果你在參與團隊中多個相關項目(也許你正在設計一個基於微服務的架構),那麼工作區可能會是你非常需要的功能。如果你有一個包含 100 個微服務的架構,所有微服務都依賴同一組模塊,那麼你可以想想這個新特性會為你節省多少磁碟空間。這個特性的用武之地就是類似這樣的場景!

PeerDependencies 自動安裝

我今天要介紹的第二大特性就是它。之前我們必須手動安裝對等依賴項,以後就用不著了。但是首先,到底什麼是對等依賴項呢?

如果你不太熟悉這個術語(以前我也不熟),這裡就簡單介紹一下:對等依賴項和普通的依賴項幾乎沒什麼區別,它們並沒有定義一個嚴格的要求,而是聲明:

你的軟體包與另一個模塊的特定版本兼容。如果該模塊已經安裝並且是正確的版本,則不要執行任何操作。如果找不到該模塊或版本存在衝突,則向開發人員顯示一條消息,警告他們這一事實,此外什麼也不做。理論上講這都沒什麼問題,但如果你要自動安裝這些依賴項,那麼當你添加兩個具有相同依賴項但版本不同的軟體包時,兩個版本就會同時安裝(其中一個位於常規的 node_modules 文件夾中,另一個作為需要它的包的子依賴項)。

這可能會導致不兼容的問題,想像一下,我們把依賴模塊 B 的模塊 A(模塊 A 又依賴 React@15)添加到依賴 React@16 的項目中。因為 A 需要版本 15,所以它也將會把版本 15 添加為依賴項,最後依賴項樹會變成這個樣子:

- React@15- A- B +- React@16也就是說你得安裝兩個不同版本的 React,僅僅因為你需要模塊 A。但現在我們有了 Arborist,它可以分析整個樹並考慮對等依賴,如果出現衝突它就會顯示對應的錯誤信息,並且中止流程。本質上來說,NPM 現在替開發人員完成了這部分工作,並幫助後者決定是否安裝這一對等依賴項。考慮到依賴管理的工作也許會浪費一整天的時間,這絕對是一個非常有用的功能。

以前你遇到過這樣的坑嗎?這個新特性是不是讓你非常激動?

NPM 版本 7 已發布,其中包含一些新特性和改進。這兩項特性尤其吸引了我的注意,我很快就去嘗試它們了。當處理具有多個共享依賴項的大型組合項目時,工作區可以從根本上改善開發人員的體驗。

對等依賴管理的改進肯定會為使用基於 NPM 的工具的 React 開發人員帶來好處,因為這一特性在這個生態系統中是非常常用的。

你喜歡這些特性嗎?還有哪些更新你覺得是很有用的?請在下方留言並分享你的看法。

延伸閱讀

https://blog.bitsrc.io/npm-7-this-is-what-i-call-an-update-de17a34ab787

Web 開發人員應避免的 5 個錯誤-InfoQ

關注我並轉發此篇文章,私信我「領取資料」,即可免費獲得InfoQ價值4999元迷你書,點擊文末「了解更多」,即可移步InfoQ官網,獲取最新資訊~

相關焦點

  • npm install 的玄機
    轉自https://juejin.cn/post/6902992287974817806#heading-1背景某次更新common包的時候筆者踩了很多坑,沒想到簡單的一個npm install命令背後還有這麼多的學問(keng),於是藉此機會學習一下,也將個人思考與大家分享。
  • NPM 發布 TS 包
    主要參考這篇文章,這是對應的倉庫。為什麼要用 TS使用這個包的人,可以使用 ts 或 js。但如果你只用 js 寫的話,當你的包變流行之後,ts 使用者就需要類型定義,這時再加的話,就耗時間、易出錯還難更新。當你在代碼文件中寫了類型定義,使用者就不需要單獨去下載 @types/xxx 類型定義了。即使使用者不用 ts,但一些編輯器也會根據類型定義給你更好的代碼提示。
  • 你應該知道的 NPM 知識都在這!
    很多 Node.js 開發者,都知道有 package.json 這個文件,也多少都了解一些 npm 知識,但是可能沒有系統的學習過,這部分的知識對於開發一個  cli 工具,發布自己的 npm 包都很常用,開發中也會經常用到npm script內容,系統的學習一下確實會有所幫助,上面三個場景如果你都用不到,配置上節約時間,知其所以然也是有必要的!
  • NPM命令實用使用技巧總結
    使用npm install來安裝,你可以使用其簡寫npm i無需為你要安裝的每個模塊都輸入一遍npm i指令,像這樣:npm i gulp-pugnpm i gulp-debugnpm i gulp-sass你只需要輸入一行命令即可一次性批量安裝模塊npm i gulp-pug gulp-debug gulp-sass
  • 前端工程化 - 剖析npm的包管理機制
    1.1 必備屬性package.json 中有非常多的屬性,其中必須填寫的只有兩個:name 和 version ,這兩個屬性組成一個 npm 模塊的唯一標識。private如果將 private 屬性設置為 true,npm將拒絕發布它,這是為了防止一個私有模塊被無意間發布出去。
  • 【 Node.js】你應該知道的 NPM 知識都在這!
    為什麼寫這篇文章很多 Node.js 開發者,都知道有 package.json 這個文件,也多少都了解一些 npm 知識,但是可能沒有系統的學習過,這部分的知識對於開發一個  cli 工具,發布自己的 npm 包都很常用,開發中也會經常用到npm script內容,系統的學習一下確實會有所幫助,上面三個場景如果你都用不到,配置上節約時間,
  • Facebook 新推 Yarn,或取代 npm 客戶端
    我們還試圖為 npm 的 shrinkwrap 功能尋求優化方案,這個工具是用來鎖定依賴版本號的。但Shrinkwrap 功能的文件默認不會生成,如果開發者忘記了生成這一步驟,文件就不會被同步更新,因此我們編寫了一個工具,以確定 Shrinkwrap 的文件內容和 node_modules 目錄中的文件相符。
  • 使同事羨慕不已的8個npm命令
    這篇文章會為你揭示一些有用的 npm 技巧,由於篇幅原因不可能涵蓋所有,所以我選擇了工程師日常相關且有用的作為本篇文章的關注點。
  • 前端工程化 - 剖析npm的包管理機制(完整版)
    1.1 必備屬性package.json 中有非常多的屬性,其中必須填寫的只有兩個:name 和 version ,這兩個屬性組成一個 npm 模塊的唯一標識。private如果將 private 屬性設置為 true,npm將拒絕發布它,這是為了防止一個私有模塊被無意間發布出去。
  • 【 Node.js 進階】你應該知道的 NPM 知識都在這!
    為什麼寫這篇文章很多 Node.js 開發者,都知道有 package.json 這個文件,也多少都了解一些 npm 知識,但是可能沒有系統的學習過,這部分的知識對於開發一個  cli 工具,發布自己的 npm 包都很常用,開發中也會經常用到npm script內容,系統的學習一下確實會有所幫助,上面三個場景如果你都用不到,配置上節約時間,
  • npm 腳本命令學習筆記
    #查看當前項目的所有 npm 腳本命令#(其實也可以在package.json的看scripts對象裡有什麼屬性)npm runnpm的原理??每當執行npm run,就會自動新建一個 Shell,在這個 Shell 裡面執行指定的腳本命令。
  • 【小心得】npm run多個script
    ►串行執行只需要使用&&把多個npm script連接起來即可,例如:npm run s1 && npm run s2這樣就可以嚴格按照s1,s2的先後順序執行►並行執行將並行的&&符號改成&,把多個npm script連接起來,例如:npm run s1 & npm run s2此時s1和s2的執行先後順序不確定。
  • npm指令無效、npm install失敗( 雲函數上傳失敗)解決方法
    掃描文末二維碼,或者微信搜索:ZA源碼,關注微信公眾號,得一手資訊1. npm指令無效  這是由於環境變量問題導致的,請按一下步驟操作: Nodejs安裝包可在微信公眾號:ZA源碼,或掃描文末二維碼關注,在公眾號回覆:Nodejs,即可獲得。右鍵我的電腦選擇屬性
  • npm 發布 npm@6 包管理器,並提供新的安全保護
    npm 公司宣布推出 npm@6 軟體包管理器。 它將提供強大的新安全功能,例如,當開發人員嘗試使用具有已知漏洞的開原始碼時,它可以自動發出警告。
  • 你不知道的 Npm(Node.js 進階必備好文)
    為什麼寫這篇文章很多 Node.js 開發者,都知道有 package.json 這個文件,也多少都了解一些 npm 知識,但是可能沒有系統的學習過,這部分的知識對於開發一個  cli 工具,發布自己的 npm 包都很常用,開發中也會經常用到npm script內容,系統的學習一下確實會有所幫助,上面三個場景如果你都用不到,配置上節約時間,
  • npm v5.0.0 正式發布,改進了穩定性 - OSCHINA - 中文開源技術交流...
    npm 5 有了很大的進步,在幾乎所有常見的情況下顯著地改進了其性能,修復了很多由架構導致的舊的錯誤,使其更穩定和具有更好的容錯性。這對於需要一致性/安全保證的用戶是個好消息,新版還為 git 依賴提供了語義化支持。
  • 從 0 開始發布一個無依賴、高質量的 npm 包
    包的同學,可能會對NPM對開發有一種蜜汁敬畏,覺得這是一個很高大上的東西。下面我就以最近開發的「DigitalKeyboard 數字鍵盤 NPM」 為例,一一列出具體步驟:1、寫基礎模塊代碼;2、註冊npm帳號;3、配置package.json;4、配置webpack;5、添加單元測試;6、完善README.md;7、發布1、2、3足可以完成一個npm,
  • 【第596期】npm scripts
    正文從這開始~npm 不僅可以用於 模塊管理,還可以用於 執行腳本。package.json 文件有一個 scripts 欄位,可以用於指定腳本命令,供 npm 直接調用。其中 commit.sh 文件內容為:
  • 什麼才算是真正的情人?有這四種感覺才是真愛
    而真正的情人,往往是讓彼此更美好,有這三種感覺,那才算是真愛。1.彼此理解和懂得對方我們常說要和對的人在一起,可什麼才是對的人呢?所謂對的人,其實就是一種默契,彼此理解,彼此懂得對方想要的東西,兩個人在一起很舒服。
  • 什麼樣的感覺才算是真正的喜歡上了一個人?
    什麼樣的感覺才算是真正的喜歡上了一個人?1、什麼樣的感覺才算是真正的喜歡上了一個人?看到這個標題就瞬間想到他。7、一條溫柔的語音可以聽一整個月。8、朋友說我對著手機笑得像個花痴。9、就是時不時就想找他聊天啊,然後的悄悄設一個專屬的鈴聲呀。