使用 Paket 替代 Nuget.exe






4.14/5 (4投票s)
Paket 是 Visual Studio 中默认的 NuGet 包管理器的一个替代方案。Paket 与 NuGet 完全兼容,但功能更丰富,并为库开发人员提供了切实的优势。
引言
Paket 是 Visual Studio 中默认的 NuGet 包管理器的一个替代方案。Paket 与 NuGet 完全兼容,但功能更丰富,并为库开发人员提供了切实的优势。
背景
直到最近,我才听说过 Paket。我从未考虑过 NuGet 的替代品,因为它(几乎)能满足我想要的一切。唯一需要用 OctoPack 来补充 NuGet 的地方是获取程序集版本号的自定义脚本。以及在 PowerShell 中做一些胶水逻辑。嗯。也许确实有*更好*的东西。
使用 Paket
首先,我建议你去 Paket 网站阅读一些资料。Paket 与 NuGet 不同。他们正在开发一个 Visual Studio 插件,但目前非常不完善。取而代之的是,你将从头开始手动创建 Paket 文件(好吧,大部分如此)。Paket 包含一个将基于 NuGet 的项目转换为基于 Paket 的项目的命令,我们稍后会介绍它。
安装 Paket
你可以通过标准的 Visual Studio 包管理控制台从 Nuget.org 安装 paket。
接下来,你想要安装 Paket Power-Shell 工具。
现在,你可以通过 Paket 的 ConvertFromNuGet 命令将你的项目转换为使用 Paket。
在解决方案资源管理器中,你会注意到 packages.config 已消失,取而代之的是解决方案级别的 paket.dependencies 和项目级别的 paket.references。
paket.dependencies 文件用于保存被引用的程序包的定义。paket.references 文件用于保存对 paket.dependencies 中定义的程序包的项目级依赖。
你可以手动修改这些文件,但一旦创建,你应该只使用包管理器控制台让 Paket 来管理它们。
现在,让我们添加对 Newtonsoft.Json 的引用。为什么不呢?大家都这么做。:)
如果我们查看我们的 paket.dependencies,我们会看到
source <a href="https://dotnet.myget.org/F/dotnet-core/api/v3/index.jsonsource">https://dotnet.myget.org/F/dotnet-core/api/v3/index.json source</a> <a href="https://dotnet.myget.org/F/cli-deps/api/v3/index.json">https://dotnet.myget.org/F/cli-deps/api/v3/index.json</a> source <a href="https://api.nuget.org/v3/index.json">https://api.nuget.org/v3/index.json</a> framework >= net452 nuget Paket 5.84.0 nuget newtonsoft.json
现在我们的解决方案中引用了 newtonsoft.json。做得好!
继续在你的项目里编写代码。然后是时候打包并将它发送到你最喜欢的 NuGet 仓库了。
要打包你的项目,你需要另一个文件:paket.template。这个文件放在你想要在解决方案中发布的*项目*文件夹里。
GPS.SimpleDI 项目的一个示例文本 paket.template 如下所示
paket.template 文件功能非常强大。把它想象成加强版的 Nuspec 文件。它更容易阅读和编辑,并且拥有更多功能。Paket 的包构建器功能非常全面。所有这些都通过 paket.template 文件进行控制,包括和排除。模板中包含的属性(例如 **authors**)将按原样复制并放入 NuGet manifest。被省略的项则从 AssemblyInfo 数据中引用。这使得你的模板可以轻松地与你的 AssemblyInfo 文件保持一致,而不必担心不匹配。此外,这意味着你只需要在一个地方管理版本(NuGet.exe 完全做不到这一点),通过使用 `AssemblyInfo` 中定义的 `AssemblyVersion` 属性。
一旦你定义了模板,打包项目就非常容易了。Paket 的 pack 命令提供了许多选项来打包你的项目。我建议你花一些时间仔细研究那个页面,找出最适合你项目的选项集。大多数选项都可以在 paket.template 文件中找到,以使事情更简单。
为了让我的生活更轻松,我为我的解决方案(而不是项目)添加了两个自定义文件:*ReleaseNotes.txt* 文件和*deploy.ps1* 文件。deploy.ps1 文件负责编译、打包和将你的项目推送到 nuget.org(或任何你喜欢的仓库)的所有繁重工作。*Deploy.ps1* 将读取 ReleaseNotes.txt 的内容,并将其包含在 paket pack 命令中。
不幸的是,在撰写本文时,Paket PowerShell Cmdlet 没有为 pack 命令定义 Cmdlet。这很不幸,因为你的 deploy.ps1 文件中会包含一些非 PowerShell 的内容。
供参考,这是我为前面提到的 GPS.SimpleDI 项目准备的 deploy.ps1。
function Deploy-Package { param( [Parameter(Mandatory=$true)][string]$SolutionDir, [Parameter(Mandatory=$true)][string]$BuildDir, [Parameter(Mandatory=$true)][string]$Namespace, [Parameter(Mandatory=$true)][string]$Assembly ) $proj = $SolutionDir + '\' + $Namespace + '\' + $Namespace + '.csproj' $assm = $BuildDir + '\' + $Assembly & "F:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64\msbuild.exe" $proj /p:Configuration=Release if($LASTEXITCODE -eq 0) { $AssemblyVersion = [Diagnostics.FileVersionInfo]::GetVersionInfo($assm).FileVersion $packageName = $Namespace +'.' +$AssemblyVersion+'.nupkg' $package = $BuildDir +'\' +$packageName $destination = $BuildDir + '\' + $packageName + "\" + $packageName $sourceDestination = $BuildDir + '\' + $packageName + "\" + $Namespace +'.' +$AssemblyVersion+'.symbols.nupkg' Set-Location $SolutionDir $releaseNotes = [IO.File]::ReadAllText($SolutionDir + "\ReleaseNotes.txt") .paket/paket.exe pack --release-notes $releaseNotes --symbols -v $package Paket-Push -File $destination -ApiKey $env:NugetAPIKey -url https://nuget.net.cn -endpoint /api/v2/package -Verbose } }
Clear-Host
#Deploy-Package -SolutionDir %1 -BuildDir %2 -Namespace %3 -Assembly %4 Deploy-Package -SolutionDir 'F:\GPS\SimpleDI\SimpleDI' -BuildDir 'F:\GPS\SimpleDI\SimpleDI\GPS.SimpleDI\bin\Release' -Namespace "GPS.SimpleDI" -Assembly "GPS.SimpleDI.dll"
一些注意事项
- deploy.ps1 文件提供了一个用于构建、打包和推送包的函数。这个函数可以被制成 PowerShell 模块并重用。
- msbuiild.exe 的位置应该参数化。
- 你用来推送包的仓库 API KEY 需要远离源代码控制。我使用一个名为 NugetAPIKey 的环境变量来存储密钥。
- 我尽可能地使用了 PowerShell Cmdlet。
关注点
我从一条描述微软如何试图打压这个新兴包管理器的推文中得知了 Paket。这是因为一位 Paket 开发者采取了一个相当不正当的行动,试图通过 GitHub 上的一个 Pull Request 来 sneak in 一些“官方”的 Paket 认可到 Nuget gallery 网站。Nuget 的开发者最初接受了 PR,以为只是一些页面上的小改动。但很快就被撤销了……PR 被关闭……没有给出任何真正的解释。所以现在我们有两个略显可疑的行为。Paket 开发者真的不应该试图颠覆正常的 PR 流程来使他的项目受益,而 Nuget 的开发者应该更坦诚地解释关闭 PR 的原因。这个戏剧仍在上演中。在你站队之后(我并不建议这样做),祝你好运。
结论
有时我们会在生活中盲目地行走,因为我们已经身处一片绿洲,而不知道还有更美好的地方。NuGet 真的很好。如果不是因为 NuGet,微软将迅速失去优势。NuGet 是一个改变游戏规则的工具,从一开始就是如此。
Paket 只是让 NuGet 生态系统变得更好。它并没有改变生态系统的任何一个方面,它只是提供了一个更好的“老鼠夹”来利用它。