6

Blazor unified project design · Issue #49079 · dotnet/aspnetcore · GitHub

 1 year ago
source link: https://github.com/dotnet/aspnetcore/issues/49079
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Comments

Member

In .NET 8 we plan to add a new project template, Blazor Web Application, that covers all combinations of server-hosted projects (traditional Blazor Server apps, Blazor WebAssembly hosted, and the new unified architecture that allows use of Server, WebAssembly, and SSR in a single project). It will work by multitargeting over net8.0 and net8.0-browser.

However we still have to decide on the conventions for how such a project should be structured. The biggest question is what determines which files/references are included in which compilation?

Goals

  • Make it obvious what ends up in which compilation. In particular, avoid unintended inclusion in the WebAssembly compilation, because (1) it bloats the app size, and (2) in the worst case, a developer might include sensitive business logic/secrets without realising it.
  • Stay compatible with existing ASP.NET Core conventions. We don't want to break all existing docs/tutorials/etc for MVC, gRPC, auth, EF, and so on. Nor do we want people upgrading an existing nontrivial ASP.NET Core app to have to make a lot of changes to their existing code.
  • Maximize clarity; minimize the concept count. Try to make the structure intuitively obvious and pleasant for people who don't know why all this stuff works as it does. In particular, be very careful about terminology given the amount of ambiguity (e.g., client vs browser vs WebAssembly all might seem to mean the same thing here, but all of them also seem wrong in some cases).
  • Work without tying people to particular project structures. We're not designing just for the default templates; we're looking for a system that will make sense even when people change their project structures a lot, or are upgrading existing real-world projects that involve a lot of unrelated concepts they might not even fully understand.

Possible designs

I think there are two three main approaches to pick from, as depicted here (click to expand):

image

Benefits of approach A ("single project, exclude by default")

  • Does not break existing ASP.NET Core server apps. Upgrading is easy, because nothing goes into your WebAssembly compilation by default, so it's not going to give you hundreds of build errors and force you to rename files or add #if or special exclusions to your .csproj.
  • As you add more components/classes to the project, you're forced to make an explicit choice if you want to make it available to WebAssembly. There is minimal risk of accidental disclosure, and the trimmed wasm bundle will be as minimal as possible.

Its main drawbacks are that the concept of ClientShared is nonobvious (and I spent ages coming up with that name, as almost everything else fails to communicate the idea that you're making stuff available to both client and server whereas otherwise it's server only - better name suggestions are welcome, but don't just say "client" or similar).

Benefits of approach B ("single project, include by default")

  • Most similar to MAUI
    • We could even have Platforms/Browser but that's largely pointless since for almost everything you include in browser, you also want it to be available in server (otherwise, for example, you can't even route to @page components that aren't in the server build and would get 404s).
    • We could have Platforms/Server but again that's quite bad because people don't want to restructure their ASP.NET Core projects to move everything for the server into that subdir.
  • Looks simpler, because there are fewer folders
  • More obvious that what determines each component's render mode is @rendermode and not which folder it is in

Its main drawback is that it is incompatible with typical ASP.NET Core projects, at least until developers manually exclude everything that can't work in WebAssembly, and then as you work on the project you have to keep excluding more things or unintentionally include them in the WebAssembly build. In the above example, all the .razor components end up in the wasm build pointlessly, increasing its size just because it's painful to keep excluding things.

Benefits of approach C ("two projects")

  • No need for multitargeting
  • No need for any new naming or folder conventions that include/exclude things
  • No need for new rules about annotating project/package references with ClientOnly/ServerOnly/ServerAndClient/etc
  • Potentially an easier approach for people adding WebAssembly support to an existing ASP.NET Core server app (the .Client project could be a template in itself)

Its main drawback is that it gives up the multitargeting-based way to call server-only code from components that are shared with WebAssembly. For example, with approaches A and B, you could use #if SERVER inside a component to have a block of code that calls AppDbContext directly, with an #else block that runs on WebAssembly and maybe does an HttpClient call. That wouldn't work with option C because the .Client project couldn't reference types that live in the server project (there's no project reference in that direction). It means developers have to go back to traditional interfaces+DI, e.g. IMyRepository with different implementations for server and WebAssembly, since they can't just use #if SERVER etc.

In terms of whether the two-project system is harder to understand for total .NET newcomers, I honestly don't know. An extra project is an extra concept, however multitargeting and filename conventions are probably even thornier extra concepts still.

Proposal

As you can probably tell, between options A and B I'm currently leaning towards option A, however I'm still undecided on a preference between A and C. In the long term, having a single project will probably be an essential element of #46400, which may be a major feature for Blazor in .NET 9. So I suspect that's a likely direction eventually, however it doesn't mean that developers necessarily benefit in .NET 8 - there's an argument for keeping a simpler project system in .NET 8 and giving the single-project-multitargeting-conventions system more bake time. But perhaps I'm missing something about why we need to do a particular thing now in .NET 8.

If you have any feedback on what is wrong or missing from this analysis, please comment below!

cc @dotnet/aspnet-blazor-eng


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK