iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 13
5
Modern Web

平時沒注意的 JavaScript - JS 生態系及週邊工具整理系列 第 14

package-lock.json 有什麼用,淺談 Yarn, NPM5 與 npm shrinkwrap

Hello 大家好

昨天我們基本上將 npm install, package.json, node_modules 內部的機制討論了一番

不過其實有一個小問題大家可能沒注意到

package.json 的問題

我們來打開看看 package.json

{
  "name": "my-project",
  "version": "1.0.0",
  "description": "this is my project",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "alxtz",
  "license": "ISC",
  "dependencies": {
    "selenium-webdriver": "^3.6.0"
  }
}

就我們昨天的經驗

npm install 會自動幫我們把 3.6.0 版以上的 selenium-webdriver 安裝到 node_modules 裡面

並且遞迴式的把所有被引入的 dependency 都裝完

這邊的問題是⋯⋯

「我們並沒有紀錄其他 dependency 的版本啊」

為什麼其他 dependency 也要記錄版本

要記錄版本的原因很簡單

我們在寫程式的時候,通常很重要的是要注重「向後相容」

有點像是你寫了一個 module

要注意不管你每次改了什麼

其他使用這個 module 的人,你要盡可能讓他更新的時候不會壞

(要馬就寫成另一個新 function,保留原本的行為)

但是

寫程式的時候其實很難盡善盡美

所以你才會看到不少函式庫,在主要版本號更新時 (像是從 1.0 跳到 2.0)

都會寫一長串的 changelog(功能改變)

用來告訴大家有哪些 breaking change,不要讓這些改動壞的太誇張

所以知道現在使用的函式庫版本很重要

如果你每次執行程式時,使用的函式庫版本都不一樣

這樣就對你的程式很危險了

不過你其實可以看到,疑

package.json 好像沒有幫我們紀錄很詳細的版本號耶?

他的 dependencies 只有大於 xxx 的紀錄

而遞迴加入的 dependency,則沒有任何版本紀錄

哇靠,那該怎麼辦

基本上要是你沒有做些應對的話,你的程式很有可能 npm install 後,一下爆這個一下爆那個

這個問題已經存在很久了,並且有 3 種主要的解法

  1. npm 5 以前,我們可以使用 npm shrinkwrap 來產生 npm-shrinkwrap.json,試著紀錄第一次安裝的所有版本
  2. 在 Yarn 這個套件管理器裡,他有自訂的 Yarn.lock,一樣可以保存 dependency
  3. npm 5 以後新增了 package-lock.json,功能跟 Yarn.lock 很接近

npm shrinkwrap

npm shrinkwrap 這個解法是比較舊版的作法

他產生的檔案有點類似這樣

他會詳細的紀錄

  1. 你安裝的詳細版本
  2. 你的 tarball(類似套件的壓縮檔),是從哪個 url 抓來的
  3. 一個簡單的 hash(雜湊),確認你的檔案沒損壞
  4. 一個 require 欄位,說明這個 dependency 是被哪個函式庫所要求的

npm5 package-lock.json

在 npm 5 新增的 package-lock.json 其實跟 之前的 shrinkwrap 檔案很像

唯一的差別只有在

  1. package-lock.json 每次 npm install / uninstall /update 都會去更新
  2. 可是 shrinkwrap 檔案,得要你安裝完後都得手動去使用 npm shrinkwrap 來更新

詳細內容可以參考
https://stackoverflow.com/questions/44258235/what-is-the-difference-between-npm-shrinkwrap-json-and-package-lock-json

基本上不太會去考慮兩個檔案格式是否相容的問題

因為通常你只會在 npm shrinkwrap 和 package-lock.json 間擇一

Yarn

在介紹 yarn.lock 前,我們會先解釋一下 Yarn 這個專案

其實 npm 本身有許多點被人詬病,像是就算你電腦裡的其他專案有用到同個 dependency

他不會直接複製來用,而會是在上網抓一次(所以很慢)

Yarn 是原本 Facebook 內部為了解決 npm 問題而開發出的另一套套件管理員

後來開源放出來(有很多工具原本就是大公司內部的)

他本身使用的資料庫還是 npm ,但是他對下載套件、lock 檔、終端介面做了一些優化

  1. 下載 package

    而 Yarn 本身會在你的系統裡面做一些紀錄

    如果你有安裝過類似的 package 就會複製來用

    並且支援平行下載,使得 yarn 在下載 package 時速度較 npm 快很多

  1. Yarn 是使用他自己的 lock 檔,叫做 yarn.lock

    他本身並沒有比 npm shrinkwrap 或 package-lock.json 存更多內容

    但是他的格式有特別設計成比較易讀

    會讓團隊 code review 比較方便(不過那也要你們 code review 真的會 review 到 lock file )

  2. 終端的介面

    Yarn 另一個會拿出來提的是 - 「它的介面比 NPM 漂亮」
    不但色彩比較多,而且還會有 emoji ? ?
    (不過這到底重不重要就因人而異了)

    在 GitHub 上甚至有一篇討論 「Yarn 可不可以把 emoji 關掉」的 issue
    https://github.com/yarnpkg/yarn/issues/960

該選哪個?

現在我們有三個選擇

  1. 老式的 npm shrinkwrap (NPM < 4)
  2. package-lock.json (NPM 5)
  3. Yarn

這邊個人覺得像 npm shrinkwrap 的話

由於現在許多人都有升級到 npm 5 了,有在維護的套件比較不會去使用 npm shrinkwrap

而且 npm shrinkwrap 本身有不少 bug,開發團隊為了 package-lock.json 比較不會去修

這邊建議是除非你現有的系統是使用 npm 5 以下創建的

並且升級的成本很高,不然建議是可以使用 npm shrinkwrap 以外的選項

Yarn or NPM 5

我認為這邊就偏向個人選擇了

Yarn 的確效能比較好

但是並沒有提供額外的功能使得跟 npm 差距變大

並且引入一個額外的工具使用

對團隊有時候會增加複雜度(如果是在帶人,你也會希望一開始環境越簡單越好)

npm 的開發活躍度比較高,不過使用 Yarn 的話應該會跟 Facebook 的一些工具比較好串接

我的建議是都了解如何用,再根據 Project 決定要用哪個(因為功能沒差很多,上手很快)

明天

今天的主題就到這裡了!

就這幾天的衝刺後,算是補完了 JavaScript 生態系的基本功

接下來我會考慮就 Webpack 或是 Babel, ESLint 做更深入的介紹

我們明天見!

(這是上週我在 SFJS 聽的演講,也可以參考 https://docs.google.com/presentation/d/1Xvs-f4E4owbwXVIB8Q1eat___RePBTzPTCYsaKtRj3I/edit#slide=id.g2a70d767ff_4_141)


上一篇
NPM Install 到底做了些什麼?node_modules 檔案結構 + 特性入門
下一篇
前端也需要編譯?Transpile、Compile、Minify、Uglify 基本介紹
系列文
平時沒注意的 JavaScript - JS 生態系及週邊工具整理33

1 則留言

0
尾椎
iT邦新手 5 級 ‧ 2020-12-18 15:29:31

npm version 6 已經有個npm ci 的指令,會比直接用npm install安全。

我要留言

立即登入留言