第一次接觸.Net開發的人常常會聽到一個名詞,那就是nuget。而習慣nuget的開發者通常也會常說,「你就用nuget去裝xxx套件就好了」。
可是,常常會忽略掉非.Net開發者其實聽不太懂這個術語。在這篇,我希望能夠可以給新進的.net開發者,能夠瞭解什麼是nuget,為什麼要用nuget,nuget產生的什麼 東西應該進入版控,和最重要的建議回覆nuget package的方式(網路上面很多教學都是舊版本的做法)
第一次接觸.Net開發的人常常會聽到一個名詞,那就是nuget。而習慣nuget的開發者通常也會常說,「你就用nuget去裝xxx套件就好了」。
可是,常常會忽略掉非.Net開發者其實聽不太懂這個術語。在這篇,我希望能夠可以給新進的.net開發者,能夠瞭解什麼是nuget,為什麼要用nuget,nuget產生的什麼 東西應該進入版控,和最重要的建議回覆nuget package的方式(網路上面很多教學都是舊版本的做法)
何為nuget
nuget其實就是一個中央的資源版本儲存庫,每一個資源稱之為package(套件)
。每一個package都有不同版本。
這邊我用資源兩個字,因為雖然大部份大家都是用它來管控專案用到的library,但是其實nuget也可以放一些程式, 例如7zip。
如果和別的程式語言比較,nuget就如同Java的Maven,nodeJS的npm,Ruby的Gems。
如果用安裝軟體的角度,nuget就類似Linux世界的Package Management。
nuget其實是一個open source的project(Github)。其中主要兩個部份,client端和server端。
nuget都有存在什麼資源
大家第一個映像都是nuget就是一些C# library,但是其實nuget放什麼都可以。library是最常見的,但是也有一些package其實就是一個可執行的程式。例如7zip,或一些unit test的console程式,這些類型的package可以方便在做一些自動化(Automation例如Continus Integration和Continus Delivery)的時候,環境設定變得更加簡單。
nuget也有一些特殊的library,像是各個的unit test framework的Test Adapter也可以用nuget安裝。以前,要在Visual Studio直接執行第三放的unit test framework(例如NUnit),開發者都需要傳Visual Studio的Extension才可以做到,現在因為Visual Studio的調整,只要透過nuget裝Test Adapter就可以,新的開發環境不需要記得Visual Studio要裝個Extension就可以跑測試。
也有一些變形的使用
像是 Chocolatey (微軟版本的apt-get)和 Powershell Gallery (Powershell module集中地)其實都是nuget的同分支出來的服務。Nuget詞不同含義
需要注意,在不同情境下面,nuget可能有不同含義。總共兩種情況:- 程式本身 - 有時候提到nuget指的是package management這個程式
- 微軟預設的package來源 - 因為nuget server其實可以自己建制,有些服務項MyGet可以提供私人的nuget server。所以nuget有時候指的是微軟預設提供的那個資源的Nuget Package的位置
為什麼要有nuget
nuget主要解決:
- 更好在不同專案之間使用同個package的不同版本
- 讓開發者或者做自動化建制的時候,能夠不用做任何事情專案就能夠執行
- 處理library之間的相依性。例如要用xxx需要有yyy,而且這個xxx和yyy還有可能有版本問題
- 升級library的版本
可以想像一下,在沒有nuget的時代。如果你想用一個第三方的library,通常做法是執行exe或者msi來把library裝到電腦的GAC。不過這個有幾個問題:
- 因為在GAC,如果別的開發者也要開發,但是他沒裝過怎麼辦?如果文件寫的好還可以參照文件知道要安裝,但是如果沒寫好呢?
- 如果同個library,在不同專案要使用不同版本,是不是要安裝好多個exe?
- 如果要把系統放到別的環境執行,每一次都要安裝library,如果文件沒寫好,安裝的人不知道呢?
這些問題,在nuget的到來都解決了。
nuget一些特性
- nuget是跟著專案走 - 所以專案需要的package可以跟專案走
- package之間的相依性會自動處理。例如,今天要裝一個Asp .net Mvc,nuget會自動連Json.Net也裝上,因為那個是其中一個相依
- 這個專案裝了什麼package會在一個
package.config
做記錄(.Net core用的名稱不同) - 當專建制的時候,如果package.config提到的package不存在的話,會自動下載package。
如何使用nuget
nuget有兩種使用方式:
- 用GUI
- 用Package Manager Console
1. 使用GUI
Visual Studio 2013 和 Visual Studio 2015的畫面不太一樣,但是操作都差不多。
在安裝的時候注意安裝到的專案其他就還蠻直覺。舉例今天安裝常用的Json.Net
套件:
1.1 安裝package
右鍵點選專案,選擇 Mange Nuget Package(管理nuget套件)
預設會選取左邊頁籤(VS 2015是上面)Online,這個時候可以在右上角的輸入框來輸入要搜索的套件。在確定安裝前,在上面的下拉選單可以切換是否接受 Pre Realse (預覽版)的版本。
可以看到VS 2015 的版本多上了可以選擇要安裝的Version,而2013只能夠裝最新版本。
1.2 刪除package
在頁籤的Installed裡面會列出目前有安裝的package,不要的直接點Uninstall即可。
1.3 更新package
在頁籤Update可以看到那些版本是可以更新的。在VS 2015更可以選擇要更新的版本(甚至降板)
2. Package Manager Console
Package Manager Console 其實就是Powershell。透過這種方式安裝有兩個好處:
- 如果知道Package名稱 - 速度比較快。因為UI還要搜索
- 可以傳入參數。例如用
--version
來表示要安裝的版本,--force
強制刪掉某一個package(忽略這個package的相依package) - 方便更新package版本
2.1 安裝package
基本上語法就是 Install-package {packageName}
例如:
Install-Package Newtonsot.Json
2.2 刪除package
基本上語法就是 Uninstall-package {packageName}
例如:
Uninstall-Package Newtonsot.Json
如何回覆package
基本上有3種做法:
- 對專案設定package restore - 2.7 之前的做法
- nuget 2.7 之後,什麼都不用做 - 建議做法
- 使用nuget.exe呼叫
nuget restore
(在專案的資料夾下執行,會自動找到對應的sln並且回覆package)
做法1.:對專案設定package restore
在之前版本的nuget,要回覆nuget package需要做一些設定,並且把產生出來的.nuget
資料夾要放到版控才可以。
這種做法有2個問題:
- 這個做法是在專案Build(建制)的時候 在回覆不存在的package。因為是在Build的時候做,所以第一次build會失敗,因為package還沒下載好。
- 版控要記錄
.nuget
資料夾
第一個問題比較嚴重,像之前我第一次接觸自動建制,就因為這個卡住。
因為這個原因,在nuget 2.7之後改變回覆package的做法。
如果看到這篇,請大家告訴大家,建議不要在用上面描述那種方式做nuget回覆。
做法2.建議:nuget 2.7之後的做法 - 什麼都不用做
nuget 2.7之後的回覆方式就是:什麼都不需要做。沒錯,沒看錯,什麼都不需要做,只要建制,Visual Studio就會自己在 Build之前先把缺少的nuget package下載好。所以,如果有任何package需要在build的時候觸發,完全不會有問題。
什麼檔案應該進入版控
在官方建議的.gitignore設定是:
# 忽略 NuGet Packages *.nupkg # 忽略下載 packages 的資料夾 **/packages/* # 但是保留 build/ 資料夾, 用作於package的 MSBuild target. !**/packages/build/ # 下面這行可有可無 - 就算沒有也會自動產生 #!**/packages/repositories.config
結語
希望透過這篇,可以讓從來沒有接觸nuget的使用者瞭解並且知道為什麼要使用nuget,瞭解nuget帶來的好處和如何在新版本回覆package。
今天介紹的是如何使用nuget,在未來在介紹如何建立一個nuget package,把各位常用的自己寫的package能夠透過nuget在不同專案方便使用。