NuGet パッケージ管理
このスキルを使用するタイミング
以下の場合にこのスキルを使用します:
- NuGet パッケージの追加、削除、または更新
- ソリューション向け Central Package Management (CPM) のセットアップ
- 複数プロジェクトにわたるパッケージバージョンの管理
- パッケージの競合や復元の問題のトラブルシューティング
黄金律:XML を直接編集しない
パッケージ管理には常に dotnet CLI コマンドを使用してください。 .csproj や Directory.Packages.props ファイルを手動で編集しないでください。
# 推奨:CLI コマンドを使用
コマンド:dotnet add package Newtonsoft.Json
コマンド:dotnet remove package Newtonsoft.Json
コマンド:dotnet list package --outdated
# 非推奨:XML を直接編集
# <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
理由:
- CLI はパッケージの存在を検証し、正しいバージョンを解決します
- 推移的依存関係を正しく処理します
- ロックファイルが存在する場合は更新します
- タイプミスや不正な XML を回避します
- CPM と正しく連携します
Central Package Management (CPM)
CPM はすべてのパッケージバージョンを 1 つのファイルに集中管理し、プロジェクト間のバージョン競合を排除します。
CPM の有効化
ソリューションルートに Directory.Packages.props を作成します:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="Serilog" Version="4.0.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
</ItemGroup>
</Project>
CPM を使用したプロジェクトファイル
プロジェクトはバージョンなしでパッケージを参照します:
<!-- src/MyApp/MyApp.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="Serilog" />
</ItemGroup>
</Project>
CPM でのパッケージ追加
# Directory.Packages.props とプロジェクトファイルの両方に追加
コマンド:dotnet add package Serilog.Sinks.Console
# Directory.Packages.props での結果:
# <PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
# プロジェクトファイルでの結果:
# <PackageReference Include="Serilog.Sinks.Console" />
共有バージョン変数
関連パッケージを共有バージョン変数でグループ化します:
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<!-- 共有バージョン変数 -->
<PropertyGroup Label="SharedVersions">
<AkkaVersion>1.5.59</AkkaVersion>
<AkkaHostingVersion>1.5.59</AkkaHostingVersion>
<AspireVersion>9.0.0</AspireVersion>
<OpenTelemetryVersion>1.11.0</OpenTelemetryVersion>
<XunitVersion>2.9.2</XunitVersion>
</PropertyGroup>
<!-- Akka.NET パッケージ - すべて同じバージョンを使用 -->
<ItemGroup Label="Akka.NET">
<PackageVersion Include="Akka" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster.Sharding" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster.Tools" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Persistence" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Streams" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Hosting" Version="$(AkkaHostingVersion)" />
<PackageVersion Include="Akka.Cluster.Hosting" Version="$(AkkaHostingVersion)" />
</ItemGroup>
<!-- Aspire パッケージ -->
<ItemGroup Label="Aspire">
<PackageVersion Include="Aspire.Hosting" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.AppHost" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.PostgreSQL" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.Testing" Version="$(AspireVersion)" />
</ItemGroup>
<!-- OpenTelemetry パッケージ -->
<ItemGroup Label="OpenTelemetry">
<PackageVersion Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="$(OpenTelemetryVersion)" />
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="$(OpenTelemetryVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="$(OpenTelemetryVersion)" />
<PackageVersion Include="OpenTelemetry.Instrumentation.Http" Version="$(OpenTelemetryVersion)" />
</ItemGroup>
<!-- テスト -->
<ItemGroup Label="Testing">
<PackageVersion Include="xunit" Version="$(XunitVersion)" />
<PackageVersion Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
<PackageVersion Include="Verify.Xunit" Version="26.0.0" />
</ItemGroup>
</Project>
利点:
- 1 つの変数を変更するだけで、すべての Akka パッケージを更新できます
- ラベル付き ItemGroup による明確な整理
- 関連パッケージでのバージョン不一致を防止
CPM を使用すべきでない場合
Central Package Management は常に適切な選択とは限りません:
レガシープロジェクト
既存の大規模なソリューションを CPM に移行すると、問題が発生する可能性があります:
- 既存のバージョン競合が一度にすべて可視化される
- 一部のパッケージで意図的にバージョンが異なる場合がある
- 移行には多数のファイルを同時に編集する必要がある
推奨事項:レガシープロジェクトの場合は、段階的に移行するか、現在の方式が機能している場合はプロジェクトごとのバージョン管理を継続してください。
バージョン範囲
CPM は厳密なバージョンを必要とし、バージョン範囲をサポートしません:
<!-- CPM では非サポート -->
<PackageVersion Include="Newtonsoft.Json" Version="[13.0,14.0)" />
<!-- 正確なバージョンを使用する必要があります -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
バージョン範囲が必要な場合(稀ですが、一部のライブラリシナリオで必要)、CPM は機能しません。
古い .NET バージョン
CPM には以下が必要です:
- .NET SDK 6.0.300 以上
- NuGet 6.2 以上
- Visual Studio 2022 17.2 以上
古い SDK バージョンをターゲットにしている場合や、チームメンバーが古いツールを使用している場合、CPM はビルドエラーを引き起こす可能性があります。
マルチリポジトリソリューション
ソリューションが独立してビルドされる複数のリポジトリにまたがる場合、CPM の単一の Directory.Packages.props は役に立ちません。各リポジトリに独自のものが必要です。
CLI コマンドリファレンス
パッケージの追加
# 最新の安定版を追加
コマンド:dotnet add package Serilog
# 特定のバージョンを追加
コマンド:dotnet add package Serilog --version 4.0.0
# プレリリース版を追加
コマンド:dotnet add package Serilog --prerelease
# 特定のプロジェクトに追加
コマンド:dotnet add src/MyApp/MyApp.csproj package Serilog
パッケージの削除
# 現在のプロジェクトから削除
コマンド:dotnet remove package Serilog
# 特定のプロジェクトから削除
コマンド:dotnet remove src/MyApp/MyApp.csproj package Serilog
パッケージの一覧表示
# ソリューション内のすべてのパッケージを表示
コマンド:dotnet list package
# 古くなったパッケージを表示
コマンド:dotnet list package --outdated
# 推移的依存関係を含める
コマンド:dotnet list package --include-transitive
# 脆弱なパッケージを表示
コマンド:dotnet list package --vulnerable
# 非推奨のパッケージを表示
コマンド:dotnet list package --deprecated
パッケージの更新
# CPM の場合:Directory.Packages.props のバージョンを編集
# その後復元して適用
コマンド:dotnet restore
# CPM なしの場合:削除して新しいバージョンで追加
コマンド:dotnet remove package Serilog
コマンド:dotnet add package Serilog --version 4.1.0
# または dotnet-outdated ツールを使用(推奨)
コマンド:dotnet tool install --global dotnet-outdated-tool
コマンド:dotnet outdated --upgrade
復元とクリーン
# パッケージの復元
コマンド:dotnet restore
# ローカルキャッシュのクリア(トラブルシューティング)
コマンド:dotnet nuget locals all --clear
# 強制復元(キャッシュを無視)
コマンド:dotnet restore --force
パッケージソース
ソースの一覧表示
コマンド:dotnet nuget list source
プライベートフィードの追加
# 認証付きフィードを追加
コマンド:dotnet nuget add source https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json \
--name MyFeed \
--username az \
--password $PAT \
--store-password-in-clear-text
NuGet.config
ソリューション固有のソースには、NuGet.config を作成します:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="MyPrivateFeed" value="https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<MyPrivateFeed>
<add key="Username" value="az" />
<add key="ClearTextPassword" value="%NUGET_PAT%" />
</MyPrivateFeed>
</packageSourceCredentials>
</configuration>
共通パターン
開発専用パッケージ
<!-- Directory.Packages.props -->
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<!-- プロジェクトファイル - 開発依存関係としてマーク -->
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
条件付きパッケージ
<!-- Debug ビルドのみに含める -->
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<PackageReference Include="JetBrains.Annotations" />
</ItemGroup>
<!-- プラットフォーム固有 -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="System.Text.Json" />
</ItemGroup>
バージョンオーバーライド(緊急回避策)
どうしても 1 つのプロジェクトで CPM をオーバーライドする必要がある場合(稀):
<!-- プロジェクトファイル - 使用は控えめに! -->
<PackageReference Include="Newtonsoft.Json" VersionOverride="12.0.3" />
警告:これは Slopwatch によって検出されます(dotnet/slopwatch スキルを参照)。
トラブルシューティング
バージョン競合
# 完全な依存関係ツリーを表示
コマンド:dotnet list package --include-transitive
# 特定のパッケージを引き込んでいるものを特定
コマンド:dotnet list package --include-transitive | grep -i "PackageName"
復元の失敗
# すべてのキャッシュをクリア
コマンド:dotnet nuget locals all --clear
# 詳細なログで復元
コマンド:dotnet restore --verbosity detailed
# ロックされたパッケージを確認
コマンド:cat packages.lock.json
ロックファイル
再現可能なビルドには、パッケージロックファイルを使用します:
<!-- Directory.Build.props -->
<PropertyGroup>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>
その後、packages.lock.json ファイルをコミットします。
アンチパターン
禁止:XML を直接編集
<!-- 悪い例:手動 XML 編集 -->
<PackageReference Include="Typo.Package" Version="1.0.0" />
<!-- パッケージが存在しない可能性があります!CLI ならこれを検出できます。 -->
禁止:CPM でインラインバージョンを使用
<!-- 悪い例:CPM をバイパス -->
<PackageReference Include="Serilog" Version="4.0.0" />
<!-- 良い例:バージョンは Directory.Packages.props から取得 -->
<PackageReference Include="Serilog" />
禁止:バージョン管理の混在
<!-- 悪い例:一部のバージョンが CPM、一部がインライン -->
<PackageReference Include="Serilog" /> <!-- CPM から -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <!-- インライン -->
禁止:共有変数を忘れる
<!-- 悪い例:関連パッケージで異なるバージョン -->
<PackageVersion Include="Akka" Version="1.5.59" />
<PackageVersion Include="Akka.Cluster" Version="1.5.58" /> <!-- 不一致! -->
<!-- 良い例:共有変数を使用 -->
<PackageVersion Include="Akka" Version="$(AkkaVersion)" />
<PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />
クイックリファレンス
| タスク | コマンド |
|---|---|
| パッケージを追加 | dotnet add package <name> |
| 特定のバージョンを追加 | dotnet add package <name> --version <ver> |
| パッケージを削除 | dotnet remove package <name> |
| パッケージを一覧表示 | dotnet list package |
| 古くなったものを表示 | dotnet list package --outdated |
| 脆弱なものを表示 | dotnet list package --vulnerable |
| 復元 | dotnet restore |
| キャッシュをクリア | dotnet nuget locals all --clear |
リソース
- Central Package Management: https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management
- dotnet CLI リファレンス: https://learn.microsoft.com/en-us/dotnet/core/tools/
- NuGet.config リファレンス: https://learn.microsoft.com/en-us/nuget/reference/nuget-config-file