上禮拜才遇到一件怪事:我把 Bug 改完 deploy 上去了,結果同事 build 完跟我說「你根本沒修好」。

後來查了半天搞清楚,他本地快取抓到的是舊的 Snapshot。在 Maven 專案裡,只要沒搞懂 Release 跟 Snapshot 的運作機制,這類怪事就會天天上演。這篇就把兩者的差別和更新邏輯整理一下。

01. Release 跟 Snapshot 差在哪

簡單講:Release 發出去就固定了,Snapshot 隨時會更新。

維度 Release(正式發行版) Snapshot(快照開發版)
版本號格式 固定號碼,如 1.0.0、2.1.3 結尾加 -SNAPSHOT(必須全部大寫)
核心性質 不可變(Immutable):一旦發布嚴禁更動 可變(Mutable):內容隨時可能推進與重打
本地快取機制 下載至 ~/.m2/repository 後永遠不再拉取 依據更新策略(預設每天)檢查遠端倉庫最新快照
適用階段 正式環境(Production)、對外 API、封測歸檔 日常開發、特性分支測試、團隊內部協同
💡 重要細節提醒:SNAPSHOT 命名規範

在 pom.xml 裡,後綴必須嚴格為大寫的 -SNAPSHOT(例如 1.0.0-SNAPSHOT),前後以連字號
- 隔開。小寫的 -snapshot 會被 Maven 視為一般的純文字 Release 版本號,從而失去快照自動更新的特性!

02. 實戰場景:為什麼開發期需要 Snapshot

為什麼開發期間不能直接用 Release 版號?看一個很常見的微服務依賴情境:

假設有兩個服務:底層提供介面的 order-service,以及依賴它的前端服務
customer-ui。在密集開發階段,order-service 一天可能修修補補發布好幾次:

  • 如果都用 Release 版號:每次改一行 code,order-service 就得發一個新版號(1.0.1 →
    1.0.2)。那 customer-ui 的開發者就得跟著改 pom.xml
    裡的版本號,否則本地快取永遠拉不到新程式碼。光改版號和同步通知就煩死了。
  • 如果改用 Snapshot 版號:雙方約定好依賴 order-service-1.0.0-SNAPSHOT。雖然檔名看起來都一樣,但發布到遠端
    Nexus/Artifactory 時,Maven 底層會自動加上「時間戳記 + 建置序號」(例如 1.0.0-20241024.083015-1)。

這樣 customer-ui 在 build 的時候,Maven 會主動去對照遠端的時間戳記;只要遠端有更新的 Snapshot,就會自動抓下來覆蓋本地快取,不用每次改版都手動去改
pom.xml。

03. updatePolicy 更新策略與常見踩坑

「既然 Snapshot 會自動抓最新版,為什麼有時我重新 build 還是沒抓到?」這通常是 <updatePolicy> 設定的問題。

Maven 預設不是每次 build 都會連網檢查的。你可以透過倉庫設定裡的 <updatePolicy> 調整檢查頻率:

pom.xml 或 settings.xml — Snapshot 倉庫更新策略配置

<repositories>
  <repository>
    <id>internal-nexus</id>
    <url>https://nexus.example.com/repository/maven-public/</url>
    <snapshots>
      <enabled>true</enabled>
      <!-- 可選值:always | daily | interval:X | never -->
      <updatePolicy>always</updatePolicy>
    </snapshots>
  </repository>
</repositories>

常見的更新策略選項包含:

  • daily(預設值):每天只連網檢查一次。如果你早上 9 點建置過一次,下午同事推了新快照,本地預設是不會抓取的!除非手動下指令
    mvn clean compile -U(-U 代表強制檢查更新)。
  • always:每次執行建置命令時,都強制連線遠端倉庫檢查是否有更新版本。
  • interval:X:每隔 X 分鐘檢查一次(例如 interval:60)。
  • never:從不主動檢查遠端更新,完全依賴本地既有快取。
⚠️ 避坑提醒:別隨便把 updatePolicy 設成 always

很多人為了解決「沒抓到最新 code」的問題,索性在 settings.xml 將所有 Snapshot 都設為
always。結果專案只要依賴模組多一點,每次編譯都要對 Nexus 發幾十次 HTTP 查詢,直接把建置時間拖慢好幾倍。建議維持預設的
daily,有需要時手動加 mvn -U 強制更新就好。

04. 小結

原則其實很單純:

  • 開發階段用 Snapshot:自動抓最新程式碼,避免版號無意義一直往上加。
  • 準備上線用 Release:確保「今天測過的 jar 包,幾個月後重抓內容依然完全相同」。

把這兩者的邊界劃分清楚,團隊協作時就不會整天為了「誰沒抓到最新依賴」在那邊除錯了。

« »