dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.98k stars 4.66k forks source link

Migrate Microsoft.Extensions packages into their own Framework (and workload) #67487

Open AraHaan opened 2 years ago

AraHaan commented 2 years ago

For starters, the Microsoft.Extensions.* packages that are from this repository are great, well known, and also well used (with a majority used by tons of packages that result in a huge dependency chain of just those packages alone if you count the transitive dependencies).

Because of this I would like to suggest making them into an framework named Microsoft.NETCore.Extensions.App framework that can be used for all types of apps, This framework would replace the nuget package versions and support .NET 6 at minimum (or rather the TFM that the packages all commonly support at minimum), also make them into an workload that can be installed into the .NET 7 SDK (not the .NET 6 one).

Other changes that would need to be made:

Pros of the change:

Cons of the change:

dotnet-issue-labeler[bot] commented 2 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

teo-tsirpanis commented 2 years ago

The packages in the Microsoft.Extensions family are plain-old general-purpose libraries. They need no special SDK support to warrant their own workload. And they also have to support .NET Framework through .NET Standard 2.0, so obsoleting the NuGet cannot happen.

AraHaan commented 2 years ago

Hmm I guess the framework option could work for .NET Standard based frameworks (like .NET Framework for example) right?

Or is FrameworkReference not possible for sdk style .NET Framework projects? Although the users might not be using sdk style though 🤔.

I guess the deprecation message could be added to the .NET SDK when it sees them referencing the packages in .NET 6+ to use the workload instead.

teo-tsirpanis commented 2 years ago

I still don't understand why to make them on their own shared framework. Extensions is a library, not an app model like ASP.NET Core, Windows Desktop or MAUI. Imagine needing a shared framework for Newtonsoft.Json.

AraHaan commented 2 years ago

Newtonsoft is a single package, Extensions is not (and is often considered by many it's own framework because of that).

teo-tsirpanis commented 2 years ago

That is a miconception. Extensions is like the Windows Community Toolkit. A set of libraries that could have well resided in the BCL or in a third-party library. There's absolutely nothing special about them.

AraHaan commented 2 years ago

While that may be the case, take a look at the ASP.NET Core framework reference, almost (if not all of them) are included in it, however they could have been instead moved to their own framework that one would have to opt-into using (with asp.net core projects opting into it by default). Because of that many people thought it was a great idea to try to manually reference the ASP.NET Core framework when using:

However it would then result in failure to run the program due to that (because they want the extensions to be used from a framework and not from a package because their application is FDD and not self-contained) with it thinking that the relevant runtime is not installed (WindowsDesktop/MAUI).

That was one of the main reasons for filing the issue, along with the reasons I listed above like enabling crossgen2 on all the Microsoft.Extensions assemblies that are inside the reference to boost statup performance (which can also indirectly improve asp.net core / efcore as well).

And yes my argument is, if asp.net core apps can use them in FDD without needing the packages, so should any other type of project if they opt-in to not using the packages but still be able to use them the same way asp.net core apps can (also doing such could bring down the size of the asp.net core framework itself by at least 3~5 MB or so by having the source code to that framework also opt-in to it, it's planned to be a workload anyway so why cant workloads depend on other workloads?).

Also I forgot 1 other reason as well:

ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-meta See info in area-owners.md if you want to be subscribed.

Issue Details
For starters, the Microsoft.Extensions.* packages that are from this repository are great, well known, and also well used (with a majority used by tons of packages that result in a huge dependency chain of just those packages alone if you count the transitive dependencies). Because of this I would like to suggest making them into an framework named ``Microsoft.NETCore.Extensions.App`` framework that can be used for all types of apps, This framework would replace the nuget package versions and support .NET 6 at minimum (or rather the TFM that the packages all commonly support at minimum), also make them into an workload that can be installed into the .NET 7 SDK (not the .NET 6 one). Other changes that would need to be made: - Migrate the usage of them in dotnet/aspnetcore (and possibly other repos) to the workload version (An Sdk change would need to be made to make it know about the new workload before then). - A nuget.org change would need to be made to make it possible to obsolete the Microsoft.Extensions nuget package for that workload so they get warned to "install the workload instead". Pros of the change: - the libraries could benefit from crossgen2 for startup performance and various other things that might make them able to be optimized more than what the package version can offer. - more easier to use and less chance of a dependency version conflict (the updates would flow in when you update the workload and would update for all projects) (less chance of dll hell at runtime too). - overall the workload experience would be better than the package approach here for these well known packages that can become their own framework (because there are a lot of them that it would be more logical to make it a framework). - easier to contribute to projects depending on the workload as then it can be listed as an hard requirement to have the workload installed when you open their Visual Studio solution file. Cons of the change: - Might not support as many TFMs as the package version (unless there is a way to preserve that one too). - Would require some help to configure the workload installer generation for this in this repository, however the workload would probably need it's own SDK to insert itself into ``KnownFrameworkReference`` and define a property responsible for enabling the insertion and framework reference.
Author: AraHaan
Assignees: -
Labels: `area-Meta`, `packaging`, `untriaged`
Milestone: -
ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-extensions-primitives See info in area-owners.md if you want to be subscribed.

Issue Details
For starters, the Microsoft.Extensions.* packages that are from this repository are great, well known, and also well used (with a majority used by tons of packages that result in a huge dependency chain of just those packages alone if you count the transitive dependencies). Because of this I would like to suggest making them into an framework named ``Microsoft.NETCore.Extensions.App`` framework that can be used for all types of apps, This framework would replace the nuget package versions and support .NET 6 at minimum (or rather the TFM that the packages all commonly support at minimum), also make them into an workload that can be installed into the .NET 7 SDK (not the .NET 6 one). Other changes that would need to be made: - Migrate the usage of them in dotnet/aspnetcore (and possibly other repos) to the workload version (An Sdk change would need to be made to make it know about the new workload before then). - A nuget.org change would need to be made to make it possible to obsolete the Microsoft.Extensions nuget package for that workload so they get warned to "install the workload instead". Pros of the change: - the libraries could benefit from crossgen2 for startup performance and various other things that might make them able to be optimized more than what the package version can offer. - more easier to use and less chance of a dependency version conflict (the updates would flow in when you update the workload and would update for all projects) (less chance of dll hell at runtime too). - overall the workload experience would be better than the package approach here for these well known packages that can become their own framework (because there are a lot of them that it would be more logical to make it a framework). - easier to contribute to projects depending on the workload as then it can be listed as an hard requirement to have the workload installed when you open their Visual Studio solution file. Cons of the change: - Might not support as many TFMs as the package version (unless there is a way to preserve that one too). - Would require some help to configure the workload installer generation for this in this repository, however the workload would probably need it's own SDK to insert itself into ``KnownFrameworkReference`` and define a property responsible for enabling the insertion and framework reference.
Author: AraHaan
Assignees: -
Labels: `untriaged`, `area-Extensions-Primitives`
Milestone: -
ericstj commented 2 years ago

@eerhardt @davidfowl @maryamariyan -- thoughts on this? One thing we could consider is adding more extensions packages to the base shared framework rather than ASP.NETCore shared framework and keep the package/framework duality.

eerhardt commented 2 years ago

I don't think we will get rid of the NuGet packages. We would need some pretty strong reasoning to justify removing the NuGet packages.

I agree with @ericstj above that if we think this justifies its own "shared framework", we should just move them into the Microsoft.NETCore.App shared framework. These libraries already exist in dotnet/runtime. There would be no real benefit to splitting them into their own shared framework.

But I don't think the above is strong enough justification for doing this work. If you use these libraries outside of ASP.NET, and you need fast startup, you can publish your app with PublishReadyToRun=true, and these assemblies will be pre-compiled. If you need to share them across multiple apps in order to save size, we should enable that scenario generically for any NuGet packages before solving it specially for Microsoft.Extensions. For example, the dotnet store command was built to do something like this. If reusing libraries in a common location is necessary, something like that will solve it for everybody - not just Microsoft.Extensions.

AraHaan commented 2 years ago

What I wanted was to have them in something like a framework where they would get serviced for all of my code at once so the serviced code gets run on all of them whenever the .NET SDK updates, a lot of people could agree with me on this one.

Placing it in the base shared framework would be a good option too. While the packages might be great (they get copied to the output directory which is not always the best option for everyone). After all not everyone keeps track of package updates and that can result in security problems in their app where placing them in a shared framework would eliminate that issue as then updating the shared framework when a servicing release is issued would be a far more better (and safer) option. This is why I am reluctant to use the packages as a lot of people do not wildcard them with *-* because sometimes if they do a prerelease build might be breaking for them.

Besides they get versioned with the rest of the projects in this repo so I think having both the package option and having them in the base shared framework would be the best option (which also exists for System.Text.Json and other libraries in the base shared framework).

While dotnet-store is an option, it would not be the best option for end users who might want to use the app (as some programs that might do this might be closed source so they would not have the source code to run the command). Besides End users really just want to install the runtime & try to run the app (however it would be nice if one can tell the apphost to instead link to the sdk instead of the runtime).

eerhardt commented 2 years ago

We can leave this issue open for a while to get feedback from others in the community if they see high value in doing this work. But without overwhelming feedback that putting the Microsoft.Extensions assemblies into the shared framework would benefit a lot of users, I don't think it is likely to get implemented.

After all not everyone keeps track of package updates and that can result in security problems in their app where placing them in a shared framework would eliminate that issue as then updating the shared framework when a servicing release is issued would be a far more better (and safer) option.

Again, the Microsoft.Extensions libraries are not special in this regard. A security issue could be found in any library. There are other mechanisms for finding security vulnerabilities in your dependencies. Here's one example: https://devblogs.microsoft.com/nuget/how-to-scan-nuget-packages-for-security-vulnerabilities/.

davidfowl commented 2 years ago

I'm open to that discussion 😃

AraHaan commented 2 years ago

Another option could be to do something similar to how the WindowsDesktop shared framework has profiles and do an Extensions profile on the base shared framework that does not get used by default and for those who use that profile to gather the telemetry on (unless they opted out by environment variable). And then when more usage data is in merge the 2 profiles (when it is determined to be well used and not just on the aspnetcore repo and projects using ASP.NET Core).

ericstj commented 2 years ago

Another option could be to do something similar to how the WindowsDesktop shared framework has profiles and do an Extensions profile

I'm not sure that really solves any problem, just another implementation option. The reason this was done in WindowsDesktop was to hide API and build tooling. I don't think we really care about hiding API here -- it's already segmented well by namespace.

IMO to justify work we don't need "options" here. We need a clear set of pros/cons that makes it a winning value proposition. Ideally that could be backed with data.

ghost commented 2 years ago

This issue has been marked needs-author-action since it may be missing important information. Please refer to our contribution guidelines for tips on how to report issues effectively.

AraHaan commented 2 years ago

What I can think of so far:

Pros:

Cons:

jkotas commented 2 years ago

Less disc space wasted downloading the packages as they would be part of the base shared framework instead.

It is not true if your project depends on netcoreapp shared framework only and does not use any of these packages. We do publish packages with netcoreapp shared framework only (https://dotnet.microsoft.com/en-us/download/dotnet/6.0).

wtgodbe commented 1 year ago

If we do wind up moving these into Microsoft.Netcore.App it will require a reaction in aspnetcore, please keep me in the loop if we wind up taking that path.

trylek commented 1 year ago

We just hit this in our efforts on publishing Linux Docker containers using the combined ASP.NET + runtime Crossgen2 composite build, please see here:

In particular, we're hitting problems with the Microsoft.Extensions.Logging.Abstractions assembly because both aspnetcore and SDK reference it and they may end up picking up different versions of the assembly due to various latencies in the build.

AraHaan commented 1 year ago

Yep, that was another reason why I opened this issue as well, to discuss a way to and permanently resolve the problem via roll forward logic that already exists in the way the runtime works which I think could solve the aspnetcore and the SDK issue with it loading up wrong versions at the same time during build.