這年頭用Visual Studio寫程式已經離不開NuGet了!NuGet會在每個專案新増packages.config記錄已安裝Package及版本,在解決方案(.sln)檔所在資料夾則會建立packages保存各專案的NuGet Package DLL實體,放在解決方案層級的好處是方便Package檔案共享,專案A裝過NLog,專案B要安裝NLog時就不需要重新下載,直接參照packages裡的nlog.dll就好。
從NuGet 2.7起,Visual Studio預設啟用Automatic Packages Restore功能,只要以下兩佪選項沒有被關閉,VS會在每次編譯時檢查各專案的packages.config,自動補齊欠缺的Package。
在NuGet 2.7之前的版本,採用的還原做法是所謂MSBuild-Integrated Package Restore,如要採用這種做法,需如下圖在解決方案按右鍵啟用設定,之後Visual Studio會略過Automatic Package Restore,改用舊做法。
當啟用MSBuild-Integrated Restore,除了packages目錄,解決方案資料夾下還會再多一個.nuget資料夾,裡面有NuGet.exe、NuGet.config、NuGet.targets,方便建置時自動由NuGet補足缺少的Package。(但此點不適用Web Site Project)
新舊做法相比,Automatic Package Restore有以下優點:
- 不需額外操作設定,開發者
糊里糊塗不知不覺間就能享受到Package自動還原功能。 - 不需額外新增.nuget資料夾及檔案
- Package還原工作搶在MSBuild之前由Visual Studio執行,讓MSBuild相關的擴充套件能在編譯前被準備好。
- 支援Web Site Project!(WSP:嗚… 總算還有人記得我)
除此之外,也有透過命令列還原Package的做法,更多細節可參考NuGet文件。
使用NuGet Package Restore可減少原始碼傳送及封存時的資料量。packages資料夾包含大量dll檔,容量常常高達數百MB,啟用Package Restore後,packages不需隨原始碼打包,對方可在建置專案時再由NuGet即時下載安裝。
「packages跟.nuget資料夾該不該進版控?」的問題困擾我好一陣子了,之前沒掌握底層運作的眉角,常被一些「靈異現象」整得七葷八素,直到累積一些心得後,才有較具備的概念!(老話一句,會覺得「暗!見鬼了」多半是因為了解不夠透徹,線索掌握不足所致,真相大白後便會驚覺一切都符合科學邏輯,電腦永遠是死板板照指令辦事,從不背叛任何人。相較於江湖事,單純豈止十萬倍? XD)
packages進版控跟不進版控實務上都可行,但屬兩種不同策略,實踐時一些細節要到位,不然會搞到你欲哭無淚。
策略一:packages不進版控
新版Visual Studio與NuGet 2.7+預設已開啟Automatic Package Restore功能,理論上什麼都不做就可以做到自動邏原,故大部分的情況下packages並不需要簽入TFS。
如果你選擇使用MSBuild-Integrated Package Restore(例如:要配合Build Service或批次自動編譯),記得要開啟Enable NuGet Package Restore選項,並確認packages目錄沒有簽入TFS。之前遇過案例:package被誤簽入TFS,但預設dll、exe檔案型別不會簽入。因此TFS版控空有packages各Package的完整目錄結構,獨缺最重要的dll檔。另一位同事取得最新版本編譯專案,NuGet試著還原Package,發現該Package版本的目錄已存在於packages,便認定已下載略過還原程序。結局是專案依循參數路徑找不到dll,若不是直接報錯,就是靠Visual Studio顯神通找到自以為合用的dll頂替,搞出靈異現象。
另外,已啟用MSBuild-Integrated Package Restore的專案可以改為Automatic Package Restore,方法可以參考這篇說明。
策略二:packages進版控
如果想避免重複下載Package,或是建置環境無法連上NuGet,則可選擇將packages全部簽入TFS版控。如此另一方在取得最新版原始碼時,所需NuGet Package dll檔一併就位,直接編譯即可,不需再花功夫下載。
但有幾點要注意:
- 如果已Enable NuGet Package Restore,.nuget資料夾也要簽入
新版NuGet會在csproj中加入以下檢查,Visual Studio能自動補上.nuget資料夾,但使用MSBuild編譯時便會因.nuget不存在而出錯。<TargetName="EnsureNuGetPackageBuildImports"BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on
this computer. Enable NuGet Package Restore to download them. For more
information, see http://go.microsoft.com/fwlink/?LinkID=322105.
The missing file is {0}.
</ErrorText>
</PropertyGroup>
<ErrorCondition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')"
Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))"/>
</Target>
- 簽入.nuget、packages時要確認有包含dll及exe
預設TFS在簽入資料夾時將排除exe及dll,要記得將它們從排除清單(Excluded items)再拉回來。 - NuGet Package新増或升級時記得簽入TFS
由於不再依賴NuGet自動補檔與升級,Package如有異動記得要簽入
PS: 感謝網友徐胖胖回饋Automatic Package Restore相關資訊