一個套件可以在維護者宣布棄用之後,每月繼續被下載數千萬次。另一個套件沒有停止維護,卻可能已經不是新專案完成同一件事所必需的選擇。如果只看 npm 的下載數字,這兩種變化都不容易辨認。
哪些 Library/Utility 正在退場,哪些值得留下?這個問題值得調查,但「過時套件排行榜」回答不了它。真正要追問的是:當初讓我們安裝這個套件的理由,現在還存在嗎?如果存在,它正在替誰承擔什麼?
我的判斷是,最容易失去必要性的,是替平台補缺口、卻沒有持續承擔額外複雜度的工具。這不等於小套件都該刪掉,也不等於原生 API 永遠較好。以下以截至 2026 年 10 月 8 日的官方文件、維護聲明與 npm 資料,調查五種替代壓力,並把已證實的狀態和我的推論分開。
下載量告訴我們流量,沒有直接告訴我們選擇
Request 的 README 明示自 2020 年 2 月 11 日起棄用;inflight 的套件資訊則明示不再支援,並警告記憶體洩漏。Moment 的情況不同:它仍在維護,只是不以擴張新功能為目標。這三者不能統稱為「死掉的套件」。Request 聲明、inflight 套件資訊、Moment 最新政策
我查詢 npm 官方 Downloads API,以 2026 年 9 月整個日曆月作為共同期間。這是特意挑選來檢驗「維護狀態是否等於下載消失」的三個案例,不是隨機抽樣,也不是生態占有率。
棄用或維護模式,仍能與大量下載並存
三個案例在 2026 年 9 月仍有大量下載;長條不能用來判定新專案的採用意願。
- request(已棄用)59.699
- moment(維護模式)149.03
- inflight(已棄用)392.617
查看 npm 下載量數據表
| 套件與維護狀態 | 百萬次下載(約)/2026 年 9 月 |
|---|---|
| request(已棄用) | 59.699 |
| moment(維護模式) | 149.03 |
| inflight(已棄用) | 392.617 |
npm 官方 API,2026-09-01 至 2026-09-30,UTC 日期、首尾皆含。數值以百萬次為單位,四捨五入至小數點後三位;精確整數見來源。這是單月快照,不能證明成長或衰退。下載次數不是使用者或專案數,無法區分新增採用、間接依賴與自動化安裝,也無法量化各自占比。
資料來源API 回傳的是指定期間的下載總數,沒有提供「這次是否由工程師主動選用」的欄位。假設某個舊工具仍間接依賴 Request,建置環境在沒有快取時重新下載它,就不需要有人再次認可 Request 的設計。這是可能產生下載的機制示例;本次資料無法判定有多少下載來自這種情況。npm 統計介面與日期定義
因此,調查退場至少要拆開四件事:功能是否還稀缺、維護者還承諾什麼、新專案是否選它、既有系統是否搬得走。官方棄用聲明能回答第二件事,API 對照能幫助回答第一件事;單月下載總數無法替後兩件事作答。
這也是本文的界線:有充分證據談某些用途正在失去必要性,卻沒有足夠資料宣布這五類工具的新增採用率都在下降。
第一種:替執行環境補上標準能力的相容層
node-fetch 的原始價值很清楚:把 Fetch API 帶進 Node.js。當執行環境本身提供穩定的 fetch,只為發出基本 HTTP 請求而額外安裝它,理由就變弱了。Node.js 文件記錄 fetch 自 v21 起不再是實驗功能;本文以 Node 24 的文件為能力基準。Node.js Fetch
這是可以確認的平台吸收,而不是 node-fetch 使用量下降的證明。更不是把 import 刪掉就一定完成遷移。node-fetch 的 response body 使用 Node stream,原生 Fetch 使用 Web Stream;套件的 agent 設定與 Node 原生 Fetch 的 dispatcher 也不是同一個介面。串流消費、代理連線與取消行為,都要按實際用法比對。node-fetch 文件
HTTP client 的價值還可能在更上層。應用需要統一的錯誤分類、重試政策、驗證資訊或觀測紀錄時,有共用封裝仍很合理。原生 fetch 不會把所有 HTTP 錯誤狀態都自動變成被拒絕的 Promise;你的應用仍須決定如何處理回應。重試寫入請求,也不能只加一個迴圈而不考慮重複執行。Fetch 標準
還有一個容易忽略的轉變:Node 的 Fetch 實作以 Undici 為基礎。你少安裝一個套件,底層維護工作未必消失;它可能只是被執行環境接手。衰弱的是一個獨立安裝的理由,不一定是原來那份工程知識的價值。
第二種:把日常語法包得比較方便的工具箱
陣列查找、迭代、去除重複值,曾經是通用工具箱的重要入口。今天,Array.prototype.find、map 與 Set 已是語言的一部分。若專案只需要對簡單字串陣列去重,為它引入額外函式庫的必要性自然降低。ECMAScript 集合與陣列規格
但「有近似寫法」與「語意等價」之間,經常隔著正式環境才會遇到的資料。以下是刻意設計的反例:
const settings = { retries: null };
// _.get 的預設值只在結果是 undefined 時使用。
_.get(settings, 'retries', 3); // null
// ?? 同時把 null 和 undefined 視為需要預設值。
settings?.retries ?? 3; // 3若 null 在系統裡表示「明確停用」,機械替換就改變了業務規則。Lodash 的 get 文件界定了前者的契約;檢查工具函式的第一步,應是找出呼叫端依賴的行為,而不是比較字元數。Lodash get
同樣地,structuredClone 支援許多資料型別與循環參照,卻不是任意 JavaScript 物件的透明複製:函式、DOM 節點以及原型、屬性描述子的處理都有邊界。把所有 cloneDeep 一律換掉,不是完整的遷移策略。結構化複製演算法
防抖也不只是「晚一點執行」。Lodash 的 debounce 包含 leading、trailing、maxWait、cancel 與 flush 等選擇;如果專案依賴其中的互動語意,十行自製版本未必更便宜。Lodash debounce
所以正在承受壓力的是工具箱裡與原生能力重疊的使用面,不是「整個 Lodash 已無價值」。同一個 library 可能同時包含容易替代的便利函式與值得保留的行為契約。替換單位應該是用途,不必一開始就追求整包清空。
第三種:補足 Node.js 基礎檔案操作的工具
建立多層目錄、複製目錄、依模式尋找檔案,過去常需要額外工具。Node 24 已提供遞迴 mkdir、fs.cp 與 fs.glob;其中 cp 自 v22.3 不再是實驗 API,glob 在 v24.0 標為穩定。對執行環境固定的新腳本,這些能力值得先檢查。Node.js 檔案系統文件
以下是假設的建置腳本片段,只示範 Node 24 可以直接完成哪些工作,不宣稱與所有第三方工具完全等價:
import { mkdir, cp, glob } from 'node:fs/promises';
await mkdir('dist/assets', { recursive: true });
await cp('assets', 'dist/assets', { recursive: true });
for await (const file of glob('content/**/*.mdx')) {
console.log(file);
}應用程式能指定 Node 版本,公開套件卻要照顧使用者的最低版本;這兩者的決策條件不同。即使版本符合,也要比對符號連結、覆寫、排除規則、隱藏檔與平台路徑。第三方 glob 工具提供的選項,不能只因為內建 API 名稱相同就視為一致。
這類工具退場有三道門檻:平台先提供能力,專案再能要求相容版本,最後遷移成本才低於保留成本。第一道門檻跨過,不代表後兩道也已完成。許多所謂「過時依賴」,實際卡在支援範圍與風險分配。
第四種:為上一代架構保留契約的封裝
Request 與 Moment 容易被並列,卻代表不同的維護選擇。Request 已棄用;Moment 持續維護,並保留既有可變物件的 API。將它們簡化成「都有新的替代品」,會漏掉舊系統真正難以搬動的部分。
Moment 在 2026 年 8 月 17 日修訂政策:仍不新增面向使用者的功能,但技術維護可以繼續,也不再一概排除需要破壞性變更的 3.0。這提醒我們,不應繼續引用舊公告的「不會有 v3」當成目前承諾。Moment 政策更新
真正的遷移成本藏在契約裡。假設一段日期流程依賴操作後原物件會被修改,換成回傳新物件的工具,畫面可能仍顯示合理日期,另一段流程卻讀到舊值。替換前要盤點可變性、解析、時區與格式輸出,不只是對照方法名稱。
原生 Intl.DateTimeFormat 可以承擔許多顯示工作,但格式化一個時間點,不等於解析所有人類輸入,也不等於定義「下個月同一天」或跨日光節約時間的預約規則。ECMA-402 日期格式化
Request 的使用者也可能依賴 cookie、代理或串流設定。遷移要從應用真正使用的契約開始,再選擇新 client 或薄封裝。成熟系統暫時保留某個依賴,可以是有期限、有責任人的工程決策;「不要再新增使用」與「今天全面移除」是兩種不同指令。
第五種:替瀏覽器做它現在已經會做的事
jQuery 的部分入門用途,現在可以由 querySelectorAll、classList 與 addEventListener 完成。偵測元素進入視窗,也有 Intersection Observer 可作為基礎。若一個套件的全部價值只在這些工作,原生能力確實壓縮了它的必要性。DOM 標準、Intersection Observer 規格
但 jQuery 在 2026 年 1 月 17 日發布了 4.0。這直接否定「新專案可能不需要,所以專案已停止維護」的推論。既有外掛、生態整合與團隊熟悉度,仍可能構成保留理由。jQuery 4.0 公告
原生積木也不等於完整產品。能觀察交集,不代表已經處理圖片載入失敗、虛擬清單、焦點順序或螢幕閱讀器互動。當框架或較高層元件接手這些責任,應用不再直接安裝某個小 utility,它的工作仍可能留在整合層裡。
| 類型與原用途 | 接手的能力 | 仍需檢查的剩餘需求 |
|---|---|---|
| Fetch 相容層:讓 Node 能用 Fetch | 執行環境內建 Fetch | 串流、連線設定、最低版本 |
| 通用工具箱:簡化資料操作 | 陣列方法、Set、可選串連等 | 邊界語意、深層資料、防抖契約 |
| 檔案工具:補 mkdir、複製與搜尋 | Node 的 mkdir、cp、glob | 路徑、連結、排除規則、支援版本 |
| 舊 API 封裝:統一 HTTP 或日期操作 | 新 client、Intl 與其他日期工具 | 可變性、解析、時區、相容承諾 |
| 瀏覽器補丁:選取、事件、可見性 | DOM 與觀察器 API | 外掛、生態整合、完整互動行為 |
這是一張替代邊界表,不是衰退程度排名。每一列都可能包含活躍維護、持續有需求的產品。
AI 可能拆掉薄封裝,也可能替舊依賴續命
以下是我的機制推論:如果一個工具只包裝幾個穩定 API,需求清楚、輸入受控、容易驗證,AI 降低撰寫局部實作的成本後,維持一個外部依賴的吸引力可能下降。團隊可以選擇持有少量程式碼,而不接受整套套件的介面與升級節奏。
但產生程式碼不等於消除責任。原本由套件作者處理的邊界條件、測試、漏洞修補與版本相容,會轉移到你的 repository。生成得越容易,越需要問:這個實作出錯時,誰有能力判斷它錯了?
反方向也已出現在維護者的觀察裡。Moment 的 2026 公告認為,agent 對既有程式與文件的熟悉,可能帶動新的使用。這是維護團隊對成長來源的判斷,不能當成已證實的 AI 因果效應;本次下載資料也無法驗證它。Moment 對 agent 使用的觀察
因此,「AI 會讓 utility 消失」還不足以成為結論。它可能讓簡單程式更容易自建,也可能透過範例與舊知識反覆引入同一套依賴。套件的歷史能見度,甚至可能比它是否最適合目前環境,更容易影響自動選擇。這是需要管理的風險,而不是本文已量化的市場趨勢。
對工具作者而言,我認為更值得累積的是可驗證的正確性、明確的支援邊界、可靠文件與專業問題的測試案例。薄薄一層方便寫法容易被重做;多年整理出的失敗情境,沒有同樣便宜。
哪些值得留下?看它持續承擔的複雜度
時區資料會隨政治決策更新;IANA 明確說明資料庫會因 UTC offset、時區邊界及日光節約規則的變化而修訂。這種工作不會因為第一次實作只用了幾個函式就結束。IANA 時區資料庫
解析器、密碼學實作、複雜協定與無障礙元件也提供一個判斷方向:真正的成本可能在持續對照規格、處理惡意或意外輸入、跨環境測試和修正錯誤。這是選擇依賴時應檢查的責任,不是對任何特定套件的安全保證。
一個只有幾十行的工具,可能封裝了你不想自行負責的微妙語意;一個大型工具箱,也可能在你的專案裡只被用來完成一行原生操作。大小與價值沒有固定對應。關鍵是:移除之後,剩下的責任由平台承擔,還是其實落回團隊?
我會把判斷收斂成以下行動,而不以「零依賴」當目標:
| 當前情況 | 建議行動 | 驗收重點 |
|---|---|---|
| 原生能力已足夠,版本固定,用途單純 | 逐步替換直接依賴 | 以真實輸入驗證成功與失敗行為 |
| 原生能力接近,但邊界語意不同 | 先保留或加薄相容層 | null、錯誤、取消、時區等契約 |
| 套件棄用且應用直接使用 | 限制新增使用,安排遷移 | 找出負責人、替代方案與回退點 |
| 棄用套件由上游間接帶入 | 追查並升級或替換上游 | 不把手改 lockfile 當成根治 |
| 依賴承擔仍在變動的專業問題 | 保留並持續評估 | 維護承諾、測試、支援範圍與更新能力 |
具體執行時,先用套件管理器的依賴追蹤功能確認來源,再搜尋程式真正呼叫的功能。列出最低執行版本與重要語意,選一條小路徑替換,以既有行為測試比較成功、失敗與邊界輸入,最後確認正式建置及依賴樹。單純刪掉直接依賴宣告,未必能移除上游帶進來的副本;刪除 lockfile 也不會讓上游突然改用新 API。
回到那個仍在大量下載的套件。它可能是重要基礎設施,也可能只是遷移尚未完成的痕跡。數字本身沒有替你作出判斷。
真正值得追蹤的退場訊號,是套件原來替你承擔的工作,已經有更合適、可驗證的歸屬。 當平台接手基礎能力,工具就要靠更深的專業繼續證明價值;當團隊選擇自行持有程式碼,也要同時接下原本外包的責任。能少裝一個套件是結果,知道誰負責剩下的複雜度,才是決策。
