前一章已經把程式語言、套件管理工具與其他開發工具納入共同環境。環境可以重建之後,還要進一步管理目標系統使用的外部程式碼。只記住安裝指令,無法說明專案需要哪些功能、實際取得哪些版本,也無法在套件停止維護或出現安全弱點時判斷影響範圍。
相依管理需要回答四個問題:為甚麼採用這個相依項目、哪些程式會使用它、目前實際使用哪個版本,以及日後如何更新、替換或移除。這些資訊應該與原始碼一起變更,讓相依關係成為可以檢查的專案內容。
函式庫(Library)、套件(Package)與框架(Framework)描述的層面不同:
| 名稱 | 主要意義 | 專案如何使用 |
|---|---|---|
| 函式庫 | 提供可以由程式呼叫的功能 | 程式在需要時呼叫函式、類別或其他公開介面 |
| 套件 | 封裝程式碼、版本及必要中繼資料的發布與安裝單位 | 套件管理工具按照套件名稱、版本與來源取得內容 |
| 框架 | 提供整體結構、生命週期及擴充位置 | 專案按照框架規則放入程式碼,由框架協調主要執行流程 |
一個套件可以包含一個或多個函式庫,也可能包含命令列工具、型別定義或其他資源。因此,程式實際呼叫的是函式庫提供的介面,套件管理工具處理的則是套件及其相依關係。框架也可能透過套件發布,但採用框架通常會影響較大範圍的程式結構,不能只視為多安裝一個函式庫。
這些名稱有助於辨認責任,不能單獨決定採用方式。評估時仍要查看實際公開介面、套件內容、相依項目及框架限制,避免只按照名稱推測影響範圍。
專案在套件資訊清單中直接宣告的項目稱為直接相依。直接相依所需要的其他套件稱為間接相依或遞移相依。開發人員可能沒有在程式中呼叫間接相依,但其版本、授權與安全問題仍會進入實際安裝結果。
每個直接相依至少要記錄下列資訊:
如果無法說明某個直接相依的用途,應該先確認它是否仍由程式、建置或測試流程使用。已經沒有用途的套件會增加更新與檢查範圍,也可能讓間接相依繼續留在專案中。
套件管理工具提供的分類名稱不一定相同,但專案仍要區分套件在甚麼階段被使用:
| 分類 | 用途 | 管理重點 |
|---|---|---|
| 執行相依 | 目標系統執行功能時需要 | 必須納入執行結果與正式環境的相依檢查 |
| 開發相依 | 只在開發、格式檢查、建置或測試時使用 | 保留在開發流程中,不加入不需要它的執行結果 |
| 選用相依 | 只有特定功能或環境需要 | 未安裝時要有明確行為,並且分別驗證啟用與停用結果 |
| 間接相依 | 由其他套件帶入 | 透過鎖定檔案與相依關係檢視實際版本及來源 |
分類應該反映實際用途。把所有項目都列為執行相依雖然可能暫時通過建置,卻會擴大正式執行需要取得與檢查的內容。相反地,把執行時需要的套件誤列為開發相依,則可能讓開發環境正常、正式執行結果卻缺少必要內容。
套件能完成需要的功能,只是採用條件之一。加入目標系統前,還要確認下列面向:
下載次數、熱門程度與最近發布日期可以作為參考,但不能代替上述檢查。維護活動頻繁也不代表每次更新都適合專案。對相容性、效能或整合方式仍有疑問時,可以使用小範圍概念驗證確認最重要的不確定項目,再決定是否採用。
語意化版本(Semantic Versioning)以主版號、次版號與修訂號表達公開介面的相容性變更。遵守這項規格的套件會在不相容變更時增加主版號,在向後相容的新功能與錯誤修正中分別增加次版號與修訂號。

版本號仍是套件發布者對變更的表達,不能取代專案測試。套件可能沒有遵守語意化版本,也可能在相容版本中改變專案依賴的非公開行為。專案應該根據實際風險設定版本範圍,並以鎖定檔案保存已經驗證的解析結果。重大版本更新要先閱讀變更紀錄與遷移說明,再調整程式並執行完整驗證。
固定所有直接相依的單一版本可以縮小變動範圍,但仍要處理間接相依與後續安全修補。允許過寬的版本範圍則可能讓不同時間的安裝取得尚未驗證的版本。版本範圍負責表達可接受條件,鎖定檔案負責保存本次選定結果,兩者需要配合使用。
套件更新應該形成可以重複執行的流程:
安全修補需要按照弱點是否影響實際版本、功能是否會觸發弱點及可用修補方式決定處理順序。掃描工具的嚴重程度可以協助分類,但不能單獨決定系統的實際風險。如果暫時無法更新,應該記錄原因、降低風險的措施、重新檢查日期與停止接受例外的條件。
替換套件時,要先列出目前使用的公開介面與行為,再以相同測試比較候選方案。移除套件後,還要重新產生鎖定檔案,確認不需要的間接相依已經消失,並從乾淨狀態完成建置與測試。
軟體物料清單(Software Bill of Materials,簡稱 SBOM)記錄特定系統版本包含的套件、版本、相依關係與其他組成資訊。SPDX與CycloneDX都提供可以交換這類資訊的標準格式。
SBOM 應該從實際解析或建置結果產生,並且能對應到特定的原始碼與系統版本。只從人工維護的直接相依清單產生內容,可能遺漏間接相依或實際封裝項目。套件或鎖定檔案變更後,也要重新產生 SBOM,避免文件停留在先前版本。
SBOM 可以協助查詢特定套件的影響範圍及檢查授權,卻不會自行判定某個弱點是否能在系統中被利用。它提供的是組成資訊,仍要搭配弱點資料、系統實際用法與驗證結果進行判斷。
如果目標系統使用外部套件,或需要建立與發布內部套件,通常就應該使用所選技術生態系支援的套件管理工具(Package Manager)。它能把相依需求、版本解析及實際安裝結果轉換成可以重複執行的專案流程,減少人工下載、複製與更新造成的差異。
套件管理工具只能按照設定執行相依管理,無法替專案判斷套件是否值得信任、授權是否合適或更新後是否相容。採用工具之後,仍要定義套件來源、版本規則、檢查方式與變更流程。
不同工具的功能範圍不完全相同,常見責任包括:
弱點檢查、授權分析與 SBOM 產生不一定由同一個工具內建,也可以由其他工具讀取套件資訊清單、鎖定檔案或建置結果後完成。選擇工具時應該確認整體流程能產生需要的結果,不必要求單一工具負責所有工作。
套件資訊清單(Manifest)描述專案直接需要哪些套件、允許的版本範圍及相依分類。鎖定檔案(Lockfile)保存套件管理工具解析出的確切版本,通常也包含間接相依、取得來源與內容完整性資訊。
兩種檔案的責任不同:
| 檔案 | 回答的問題 | 變更時機 |
|---|---|---|
| 套件資訊清單 | 專案需要甚麼套件,以及接受哪些版本條件 | 新增、移除、重新分類相依或調整版本範圍時 |
| 鎖定檔案 | 這次安裝實際選定哪些直接與間接相依版本 | 套件管理工具重新解析相依關係時 |
對需要產生可執行結果的目標系統,套件資訊清單與鎖定檔案通常都要納入版本管理。安裝時應該使用工具提供的鎖定或凍結模式,在兩個檔案不一致時停止,而非直接改寫鎖定結果。供其他專案引用的套件是否保存或發布鎖定檔案,則要按照該生態系與套件管理工具的規則決定。
鎖定檔案也不能單獨保證所有環境產生完全相同的結果。套件管理工具版本、套件來源、條件式相依、執行環境及建置設定都可能影響安裝內容。共同環境還要固定相關工具版本,並從乾淨狀態執行安裝、建置與測試,才能確認結果可以重現。
專案應該提供一組共同安裝入口,讓開發、測試與自動化流程使用相同的套件管理工具及參數。文件至少要說明支援的工具版本、安裝指令、是否只安裝特定分類,以及鎖定檔案不一致時的處理方式。
套件來源(Registry)也要明確設定。專案如果同時使用公開與私有來源,應該按照套件命名範圍指定對應來源,並確認不同來源出現同名套件時的解析規則。離線或限制對外連線的環境,可以使用經過管理的內部來源或快取,但仍要保留原始來源、版本與完整性資訊,並定義同步及更新方式。
如果私有套件來源需要身分驗證,設定檔只記錄來源位置與取得敏感資訊的方式。實際存取權杖或發布用憑證要由適合的安全設定機制提供,不得寫入套件資訊清單、鎖定檔案、原始碼或執行紀錄。讀取範圍也應該按照安裝與發布用途分開,避免日常安裝流程取得發布能力。
套件管理規則需要由固定流程驗證,不能只依賴開發人員記得執行。可以在相依檔案變更及建立正式結果前執行下列工作:
自動更新工具可以建立候選變更與提供版本資訊,仍要通過相同檢查後才能採用。把多個重大更新合併成一次變更會擴大問題定位範圍,適合按照相依關係及風險拆分,逐一確認結果。
程式完全沒有外部套件、不需要發布內部套件,而且所選技術的標準功能已經涵蓋全部需求時,套件管理工具可能沒有實際工作。這種情況仍要記錄程式語言與建置工具版本,並從乾淨環境驗證建置結果。
如果外部程式碼無法透過所選生態系的套件管理工具取得,專案可以選擇將來源內容納入版本管理或建立內部套件。無論採用哪一種方式,都要記錄來源、版本、完整性、授權、修改內容與更新方法。人工複製檔案卻沒有留下這些資訊,不能視為完整的相依管理方式。
專案規模小也不能單獨作為不用套件管理工具的理由。只要存在一個需要下載、解析版本或持續更新的外部套件,使用標準工具通常就比個別維護檔案更容易重現與追蹤。
完成套件管理工具設定後,應該可以確認下列結果: