2010:npm 與套件管理生態#
事件#
2010年,Isaac Schlueter 建立 npm(Node Package Manager):Node.js 的官方套件管理器與 registry。2011年 npm 1.0 支援相依版本管理;此後 npm registry 成為世界上最大的軟體套件庫。
為何重要#
- 套件管理讓生態爆發:Express(2010)、Grunt(2012)、Gulp(2013)、React(2013)、webpack(2014)、Vue(2014)等工具與框架快速累積。
- npm 的
package.json+node_modules模式成為 JavaScript 專案的事實標準,連前端專案(不跑 Node 程式碼)也用它管理相依。 - 治裝文化(left-pad 事件,2016)的教訓:一個11行的套件被刪除導致全球建置失敗,暴露了極小套件與
semver相依鏈的脆弱性,也促進了 lockfile(package-lock.json,2017)與 yarn(2016)的出現。
理論與實用原因#
- 理論原因:模組化與組合是軟體工程的核心(Parnas 的資訊隱藏理論);npm 把「共用小模組」的邊際成本降到近零,實踐了 Unix「小工具組合」哲學。
- 實用原因:Node.js 問世時沒有內建套件管理,開發者需要手動下載相依;npm 解決「找套件、裝套件、版本相依」三大痛點。
彌補了什麼缺陷#
彌補了 JavaScript/Node 生態「無套件管理、程式碼無法重用與版本化」的缺陷——對比 Ruby gems(2004)、Python pip(2008),npm 讓 JS 生態在十年內超越所有前輩。
相關條目#
程式範例#
1. npm 的核心:package.json#
{
"name": "my-app",
"version": "1.2.3",
"dependencies": {
"express": "^4.18.0", // ^ = 相容 4.x(semver 語義化版本)
"lodash": "~4.17.21" // ~ = 相容 4.17.x
},
"devDependencies": {
"jest": "^29.0.0"
}
}
npm install express # 裝套件並寫入 dependencies
npm install # 依 package.json 還原整個環境
2. CommonJS 模組的重用#
// math.js —— 匯出
exports.add = function (a, b) { return a + b; };
// app.js —— 匯入(npm 裝的或本地模組都一樣)
var add = require("./math").add;
add(2, 3); // 5
3. left-pad 事件的教訓(2016):相依鏈的脆弱性#
// 被刪除的套件全部內容只有 11 行:
function leftpad(str, len, ch) {
str = String(str);
var i = -1;
ch = !ch && ch !== 0 ? " " : ch;
len = len - str.length;
while (++i < len) str = ch + str;
return str;
}
// 但全球無數專案 require 它——刪除後 npm install 全部失敗
// 教訓促成了 lockfile(package-lock.json)與 yarn(2016)