Node.js 學習筆記(五):NPM 宇宙 🌏

2023/11/23閱讀時間約 9 分鐘

在上一篇學習筆記中,我們認識了該如何輸出、帶入 module。除了從我們電腦的 script 輸出、帶入 module 之外,網路世界充滿了各種前人開發好的套件 (package)。若能採到巨人的肩膀上,對開發專案的效率有著無與倫比的助益。但我們該去哪裡尋找需要的套件呢?答案就是 NPM

NPM 的吉祥物竟然是袋熊,有夠可愛 ❤️

NPM 的吉祥物竟然是袋熊,有夠可愛 ❤️


什麼是 NPM?

我們先前談過 Node.js 蔚為風潮,其中一個原因是其蓬勃的支援社群,而 NPM 更是功不可沒。NPM 的全名為 Node Package Manager,顧名思義就是管理 Node.js 套件的小管家 (袋熊小管家聽起來真萌 🐻)。

NPM 主要有三大部分:

  • NPM 官網方便開發者查詢需要的套件,或是分享開發好的套件
  • 專屬的 CLI (Command Line Interface)
  • 雲端程式倉庫 (registry) 託管 JavaScript 套件

我們可以把雲端程式倉庫想像成 X 皮店到店中心。賣方 (npm 套件作者) 把貨物放到店到店中心,然後買方 (套件使用者) 到那邊去取貨 (下載、安裝套件)。中途會有和藹親切的店員協助買方取貨 (CLI 工具)。

雖然以上用了比較市儈的比喻,但 NPM 上面的套件幾乎都是免費的啦,套件使用者本身以及 public 套件作者也是不用付費訂閱。順帶一提,NPM 本身是隸屬於 Github 的團隊。


使用 NPM 的好處

簡單好用:

NPM 提供了專屬的 CLI 工具,下載和安裝套件超方便,便於管理專案的 dependency。

龐大的程式倉庫:

NPM 的程式倉庫全球最大,JavaScript 相關的套件一應俱全,包含 Express、Vue.js、React、Babel 等熱門框架和工具。

免費使用:

免付費、免申請帳號也能下載安裝 public 套件。

套件管理:

隨著專案規模擴大,套件管理容易開始不受控制。NPM 提供了套件管理工具,協助開發者管理 dependency,稍後會有更詳細的介紹。



如何透過 NPM 下載、安裝套件?

首先,我們前往 NPM 官網找尋要使用的套件,今天就讓老爸笑話打頭陣吧。

每個登錄到 NPM 的套件都會有自己的 profile 頁面,我們在這邊可以看到 Readme、熱門程度、Github 連結等等。點選 Dependencies 會看到這個套件所使用的其他套件,而 Dependents 則表示這個套件被其他哪些套件依賴 (差點咬到舌頭......)

NPM 的套件就是這樣一層一層彼此依賴相疊

接著我們看到右上角,官網很貼心地標示出 npm i give-me-joke 這組安裝指令,i 是 install 的簡寫,所以指令也可以長成 npm install give-me-joke。但是別急!在安裝套件之前,我們需要透過 npm init 在專案資料夾內建立 package.json 檔。

raw-image

終端機會要求你輸入名稱、作者名、描述等等,這些事後都可以更改,所以現階段可填可不填,一路 enter 下去即可。若 entry point 維持預設的 index.js,那稍後建立的 script 最好沿用這個名稱。最後按下 y 就完成 package.json 的建立流程囉。

raw-image

package.json 記錄了 Node.js 專案的 metadata,稍後我們安裝套件之後,還會多出 dependencies 這個項目來記錄套件與版本。此外,我們也可以package.json 分享給其他人,方便他們一鍵快速安裝裡面所有套件,這部分下面篇幅將說明。

現在終於能輸入 npm i give-me-joke 了,套件安裝完成後,回到 package.json,果然多出了 dependecies。日後接續安裝其他套件,同樣會列在這邊。

raw-image

至於版本號碼 0.5.1 前面奇怪的 ^ 符號,則是 Semantic Versioning

現在先來幾個隨機的老爸笑話吧 🤡

參考 NPM profile 的 Readme 使用套件:

const giveMeJoke = require("give-me-a-joke");

giveMeJoke.getRandomDadJoke((joke) => console.log(joke));


我們的第一則隨機老爸笑話出現了:

可惡,竟然比預期的好笑 😆

可惡,竟然比預期的好笑 😆

為什麼瑞典人開始在戰船側邊漆上條碼?這樣他們才是斯堪地那維亞人啊 (Scandinavian 包含了 scan 掃描動詞)。

太好了,我們安裝並使用了人生第一個 NPM 套件。但是回到程式碼編輯器一看,除了 package.json 以及 index.js 之外,怎麼還多了 node.modulespackage-lock.json 兩個陌生檔案啊?

竟然都上了瑞典人的賊船了 (?),我們就繼續探究下去吧~



Node.modules

當我們安裝了套件之後,NPM 會自動在我們的專案資料夾內,新增名為 node.modules 的資料夾,裡面包含了所以專案執行所需要的套件。每一個套件底下還有自己的子資料夾。

我們剛剛說過,NPM 套件會一層一層相互依賴,所以打開 node.module 後,我們隨便開啟一個笑話套件所依賴的套件 axios,你會發現它也有自己的 package.json,裡面還有其他 dependencies。而 NPM 會把這些套件全部安裝下來。

raw-image

在我們輸入 npm install 之後,NPM 會以套件開發者的 package.json 描述的版本為基礎,和我們專案的 node.modules 以及 package-lock.json 相互比對,才能計算出需要更新的套件。更詳細的介紹,可以參考 npm Install 的執行過程

由於 NPM 套件層層相依的特性,node.modules 很容易呈現爆炸的狀態,網路上甚至出現一些調侃的梗圖。既然隨機老爸笑話都跑出瑞典戰船了,那梗圖當然也找北歐系列啊 。

raw-image

除了肥大的問題之外,層層相依的特性更容易造成資安漏洞,例如大家最喜愛的 JavaScript 深拷貝好夥伴 lodash 先前就有傳出資安風險。

而為了因應這樣的問題,NPM 官方也推出了 package-lock.json。平時把 package-lock.jsongit commit 起來,穩穩鎖住版本會是比較安全的作法。

接這讓我們來看看 package-lock.json


Package-lock.json

package-lock.json 基本上是更細節版的 package.json。由於 package.json 只會紀錄專案的直接依賴套件,但誠如我們一直強調的,NPM 套件往往會依賴一層又一層的套件,這時候若沒有詳記清楚,在進行版控或多人協作時,常常會冒出莫名其妙的 bug 或資安漏洞,官方才會推出 package-lock.json

node.modules 的所有套件都會出現在 package-lock.json,並附上清楚的版本

node.modules 的所有套件都會出現在 package-lock.json,並附上清楚的版本

現在也有人開始提倡改用 node ci 直接從 package-lock.json 來還原套件,取代 node install。相關的討論歡迎參考:npm ci 與 npm install 差異



透過 package.json 一次安裝所有相依套件

前面提到 package.json 除了記錄專案的 metadata 之外,也可以分享給其他人一次安裝專案的所有套件。無論我們是從 Github 下載專案,或是接手同事的專案,都可以善用這招快速安裝相依套件。

我們來到專案的 root directory,輸入 npm install 就可以了。蛤?就這樣?真的,就是這麼簡單。但如同我們剛剛所討論到的,如果想要採取比較嚴謹的做法,可以改用 npm ci 還原 package-lock.json 的相依套件。



安裝全域套件

預設上,我們安裝的 NPM 套件,其作用域都只限於專案資料夾內,這是為了保護每個專案的套件版本不會起衝突。所以如果要安裝全域套件,也就是無論在電腦的哪個資料夾內都能使用該套件的話,於 npm install 後面加上 -g flag 即可。

我們就拿這個 cowsay 套件試試看,官方文件建議使用 npm install -g cowsay 安裝。

安裝成功,可以使用了~

在 terminal 輸入 cowsay <something> 就能讓牛說話

在 terminal 輸入 cowsay <something> 就能讓牛說話

接著我們前往其他專案資料夾執行,檢查這個套件是否真的是全域套件。

raw-image

沒問題,回到上一層資料夾後,依舊能夠使用這個套件,還順便確認了繁體中文也能使用。



結語

NPM 其實還有很多細節沒有在這篇學習筆記中碰到。本篇學習筆記只是記錄了粗淺的使用狀況與心得,更多資訊可以參考底下的附錄,網路上真的有很多大神們無私分享。

參考資料


16會員
34內容數
Bonjour à tous,我本身是法文系畢業,這邊會刊登純文組學習網頁開發的筆記。如果能鼓勵更多文組夥伴一起學習,那就太開心了~
留言0
查看全部
發表第一個留言支持創作者!