0

I recently I noticed something, that I never really paid any attention to. I Develop Software in C# and I use Nuget Packages a lot. Even though Nuget console states, that the Nuget Package is downloaded for a specific .NET version, it is always loading multiple Versions which I won't ever need.

For example I have a WPF Project, which uses the .Net Framework 4.7.2. I add a Nuget Package to that Project, and in addition to the folder net472 there are also folders for net462 net562 netstandard2.0 netstandard2.1 which I don't need at all.

what I mean here is the folder structure in the packages folder of my project.

At the Company I work at, we have about 200 Projects in our workspace with 1-5 Nugets per project on average, and I assume, all these additional files over so many projects, will take up a lot of space (my disk drive is slowly approaching its limit), so I'm wondering if there is an option or something, that will stop nuget from loading files it won't ever need. I'm using visual studio 2019.

I've searched the internet already but found noting so far, as everything that comes up, is how install a specific version of a nuget package, but not how to install it only for a specific .NET version and nothing else. Also no obvious setting in the visual studio options seems to do what I need.

help would be appreciated

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Mike
  • 3
  • 4
  • 1
    Each .nupkg package file contains everything required for all .NET versions. So there's no notion of "only downloading a selected .NET version". (Also, what do you mean by "there are also folders"? Do you mean in the .nuget directory? Please edit your question to be more specific. If you *do* mean "in the .nuget directory", what's the total size of that directory? I'd be surprised if it were a very significant part of your overall disk size. – Jon Skeet May 23 '23 at 08:25
  • what I mean here is the folder structure in the packages folder of my project. And I know it's not the only thing taking up my space, but I don't get, why it loads so much data I wont ever need, for example one nuget's size is about 10MB. And that size for 7 different .Net Versions, 6 of wich I don't need. thats 60MB for one Nuget. As I said, we have multiple nugets per project, and a rough estimate of 200 projects, maybe even more. Some projects might even have 10 nugets depending on how big it is, and I just want to clean up this space from things I'll never need – Mike May 23 '23 at 08:34
  • I'm not sure if you're already doing it but you should probably be using using a single local NuGet cache so that any duplication of NuGet package downloads amongst the 200 projects is removed. – phuzi May 23 '23 at 08:51
  • yeah, we're not doing that right now. This will at least remove the duplicates. I will give tis some thought, and discuss this with my team. – Mike May 23 '23 at 08:54
  • "what I mean here is the folder structure in the packages folder of my project" - are you using old-style projects? I'd strongly recommend updating them to the newer "SDK-style" projects, at which point I don't think this will happen. (Basically you'll get the cache automatically.) SDK-style projects are also *much* easier to manage... – Jon Skeet May 23 '23 at 09:24
  • we use them, but we also have many many old projects, which we can't update to never versions of .Net because of dependencies we have no control over. But I think I know what we have to do now, thanks for guiding me. PS: your book was a huge help in learning C# – Mike May 23 '23 at 10:14

2 Answers2

0

Yes, that's an unfortunate design decision. A NuGet package is a zip file. If a NuGet package targets different frameworks, its zip file contains the assemblies for all frameworks.

For a .NET Framework solution, NuGet by default creates a packages directory next to the solution file, which contains for each package the .nupkg file as well as its extracted contents.

It also saves a package cache in your user profile. And then there's the temp directory which contains packages that are being extracted. So all in all, it's not strange to have a package on disk at least three times, and then once for every .NET Framework project referencing it. And then once in every bin folder.

For some packages that are 1, 10 or even 100 MB, this adds up ridiculously fast, especially on smaller SSDs.

If you have many .NET Framework solutions, a solution (heh) could be to configure a global packages folder, which then contains all extracted packages for your machine as opposed to once per solution directory.

This will however mess up your <Reference><HintPath>...</HintPath></Reference> in your .csproj files, so every developer on your team will then have to configure the exact same packages and source directories.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • I was afraid something like that would be the case. I guess there is nothing I can do then. At least not out of the box. I've thought about writing a program wich reads the sln. and csproj. files to read the used versions, and deleting all the other folders or something like that. But I thought there might be something simpler I missed. – Mike May 23 '23 at 08:40
  • Yeah you can, but AFAIK a NuGet Restore will then get the packages from cache (or network) again and extract them again. – CodeCaster May 23 '23 at 08:41
0

To add to CodeCaster's answer - you can simplify things for your team by having a nuget.config file in the same folder as your solution, specifying a relative path. In our case, our solution file is in the root of the repo, so nuget.config is in the root of the repo.

If you add a nuget.config that looks something like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <config>
        <add key="repositoryPath" value=".\packages" />
        <add key="globalPackagesFolder" value=".\packages" />
    </config>
</configuration>

It tells nuget to store the packages in a path relative to the location of the nuget.config file - <root>\packages in our case. Then the packages folder gets added to .gitignore... and voila! Everyone's using a packages location that's in the same place relative to all your projects, but you're also not going to be cluttering up git (or other source control) with nuget packages. Saves us a ton of space over storing duplicate packages everywhere.

As mentioned by CodeCaster, you'll still need to update the references, but you only have to do it once and since the paths are going to be consistent for everyone, you won't need to worry about updating them again. On top of that, I'd recommend switching to <PackageReference ../> for nuget package references, and ideally switching your projects to the SDK style. (We just did that for 140ish projects, took all of a day to get 90% of them. We've since updated them to multi-target with .NET 6.0 as well, but at first we left them as .NET Framework 4.7.2. If you want some help with that, including some code samples, please feel free to message me and we'll get it set up.) With the PackageReference, the references in your csproj files look like this:

<PackageReference Include="NLog" Version="5.2.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.0" />

It doesn't directly address the question as asked, but by reducing the number of duplicate copies of packages, it should significantly reduce the actual problem that prompted the question (ie it reduces disk space consumption).