| title | Reducing Package Dependencies with project.json |
|---|---|
| description | Reducing Package Dependencies with project.json |
| keywords | .NET, .NET Core |
| author | cartermp |
| manager | wpickett |
| ms.date | 06/20/2016 |
| ms.topic | article |
| ms.prod | .net-core |
| ms.technology | .net-core-technologies |
| ms.devlang | dotnet |
| ms.assetid | 916251e3-87f9-4eee-81ec-94076215e6fa |
This article covers what you need to know about reducing your package dependencies when authoring project.json libraries. By the end of this article, you will learn how to compose your library such that it only uses the dependencies it needs.
.NET Core is a product made up of NuGet packages. An essential package is the .NET Standard Library metapackage, which is a NuGet package composed of other packages. It provides you with the set of packages that are guaranteed to work on multiple .NET implementations, such as .NET Framework, .NET Core and Xamarin/Mono.
However, there's a good chance that your library won't use every single package it contains. When authoring a library and distributing it over NuGet, it's a best practice to "trim" your dependencies down to only the packages you actually use. This results in a smaller overall footprint for NuGet packages.
Currently, there is no official dotnet command which trims package references. Instead, you'll have to do it manually. The general process looks like the following:
- Reference
NETStandard.Libraryversion1.6.0in adependenciessection of yourproject.json. - Restore packages with
dotnet restorefrom the command line. - Inspect the
project.lock.jsonfile and find theNETSTandard.Librarysection. It's near the beginning of the file. - Copy all of the listed packages under
dependencies. - Remove the
.NETStandard.Libraryreference and replace it with the copied packages. - Remove references to packages you don't need.
You can find out which packages you don't need by one of the following ways:
- Trial and error. This involves removing a package, restoring, seeing if your library still compiles, and repeating this process.
- Using a tool such as ILSpy or .NET Reflector to peek at references to see what your code is actually using. You can then remove packages which don't correspond to types you're using.
Imagine that you wrote a library which provided additional functionality to generic collection types. Such a library would need to depend on packages such as System.Collections, but may not at all depend on packages such as System.Net.Http. As such, it would be good to trim package dependencies down to only what this library required!
To trim this library, you start with the project.json file and add a reference to NETStandard.Library version 1.6.0.
{
"version":"1.0.0",
"dependencies":{
"NETStandard.Library":"1.6.0"
},
"frameworks": {
"netstandard1.0": {}
}
}Next, you restore packages with dotnet restore, inspect the project.lock.json file, and find all the packages restored for NETSTandard.Library.
Here's what the relevant section in the project.lock.json file looks like when targeting netstandard1.0:
"NETStandard.Library/1.6.0":{
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.NETCore.Runtime": "1.0.2",
"System.Collections": "4.0.11",
"System.Diagnostics.Debug": "4.0.11",
"System.Diagnostics.Tools": "4.0.1",
"System.Globalization": "4.0.11",
"System.IO": "4.1.0",
"System.Linq": "4.1.0",
"System.Net.Primitives": "4.0.11",
"System.ObjectModel": "4.0.12",
"System.Reflection": "4.1.0",
"System.Reflection.Extensions": "4.0.1",
"System.Reflection.Primitives": "4.0.1",
"System.Resources.ResourceManager": "4.0.1",
"System.Runtime": "4.1.0",
"System.Runtime.Extensions": "4.1.0",
"System.Text.Encoding": "4.0.11",
"System.Text.Encoding.Extensions": "4.0.11",
"System.Text.RegularExpressions": "4.1.0",
"System.Threading": "4.0.11",
"System.Threading.Tasks": "4.0.11",
"System.Xml.ReaderWriter": "4.0.11",
"System.Xml.XDocument": "4.0.11"
}
}Next, copy over the package references into the dependencies section of the library's project.json file, replacing the NETStandard.Library reference:
{
"version":"1.0.0",
"dependencies":{
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.NETCore.Runtime": "1.0.2",
"System.Collections": "4.0.11",
"System.Diagnostics.Debug": "4.0.11",
"System.Diagnostics.Tools": "4.0.1",
"System.Globalization": "4.0.11",
"System.IO": "4.1.0",
"System.Linq": "4.1.0",
"System.Net.Primitives": "4.0.11",
"System.ObjectModel": "4.0.12",
"System.Reflection": "4.1.0",
"System.Reflection.Extensions": "4.0.1",
"System.Reflection.Primitives": "4.0.1",
"System.Resources.ResourceManager": "4.0.1",
"System.Runtime": "4.1.0",
"System.Runtime.Extensions": "4.1.0",
"System.Text.Encoding": "4.0.11",
"System.Text.Encoding.Extensions": "4.0.11",
"System.Text.RegularExpressions": "4.1.0",
"System.Threading": "4.0.11",
"System.Threading.Tasks": "4.0.11",
"System.Xml.ReaderWriter": "4.0.11",
"System.Xml.XDocument": "4.0.11"
},
"frameworks":{
"netstandard1.0": {}
}
}That's quite a lot of packages, many of which which certainly aren't necessary for extending collection types. You can either remove packages manually or use a tool such as ILSpy or .NET Reflector to identify which packages your code actually uses.
Here's what a trimmed package could look like:
{
"dependencies":{
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.NETCore.Runtime": "1.0.2",
"System.Collections": "4.0.11",
"System.Linq": "4.1.0",
"System.Runtime": "4.1.0",
"System.Runtime.Extensions": "4.1.0",
"System.Runtime.Handles": "4.0.1",
"System.Runtime.InteropServices": "4.1.0",
"System.Runtime.InteropServices.RuntimeInformation": "4.0.0",
"System.Threading.Tasks": "4.0.11"
},
"frameworks":{
"netstandard1.0": {}
}
}Now, it has a smaller footprint than if it had depended on the NETStandard.Library metapackage.