Skip to content

[Blazor] Better JS integration / modernization #52819

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
javiercn opened this issue Dec 14, 2023 · 4 comments
Closed

[Blazor] Better JS integration / modernization #52819

javiercn opened this issue Dec 14, 2023 · 4 comments
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one Pillar: Technical Debt

Comments

@javiercn
Copy link
Member

javiercn commented Dec 14, 2023

History

The Blazor JS APIs have grown organically since the initial prototype without a lot of careful thought on structure and architecture. We've continuosly added code to support the necessary features across different versions and scenarios. This has made making changes to the code hard and error prone. It's also made it hard to understand the code and how it all fits together.

At the same time, integrating Blazor with other JS toolchains has been hard as the infrastructure to build Blazor apps doesn't integrate well with other JS toolchains in the ecosystem. This has made it hard to use Blazor with other JS tools and frameworks.

For .NET 9.0, we want to take a step back and refactor our current code base to make it easier to maintain, more modular, and easier to integrate with other JS tools. There is an internal aspect to it (our build infrastructure), and an external aspect to it, the shape of the outputs we generate, as well as missing gaps in functionality.

Goals

  • Simplify integrating Blazor with other build tools. You should be able to post-process the output from a Blazor app with any JS toolchain (e.g., webpack, rollup, etc.) to further process the output (inline, minimize, etc.).

  • Simplify integrating Blazor with other JS frameworks. You should be able to import Blazor, boot it, and render components using standard JS idioms (i.e., import, await, etc.). This implies the point above.

  • Adopt modern patterns and practices in the Blazor codebase. Producing an ES6 bundle that can be used from JS or further processed by other tools, splitting the output code into multiple pay for play chunks (web, webassembly, server).

  • Simplify consuming JS libraries within Blazor applications. This encompases integrating non UI libraries (e.g., moment.js) as well as UI libraries (e.g., bootstrap, material, HTMX, React, Angular, etc.).

Details

Consuming the output from a Blazor app inside a JS app is complex as it requires custom code to setup and wire up Blazor into the JS process. The output we produce can't be consumed directly from JS toolchains, as it is not in a format that they can understand. Consuming the output form publish is challenging and consuming the output from build is not even possible. This forces users to publish the app everytime, and include custom steps in order to load the app into their own frameworks every time they make a change. This results in a less than ideal inner loop experience. There is also no way to distinguish between the different environments (typically development and production), which results in the production assets being used during development.

In addition to this, the content from Blazor is not very friendly for consumption from modern JS toolchains. We produce a single bundler that uses custom code to download and bootstrap the user application. This creates challenges as JS tools can't understand this custom dependency chain and process it out of the box, forcing custom integrations with different bundlers; mainly to teach the bundler how to copy the files to the output folder. This in turn, precludes bundlers from optimizing the entire output from the app.

Finally, the other challenging aspect is integrating existing libraries within an existing Blazor app or Razor Class Library. It normally requires manually downloading the JS dependencies and checking them into source control or manually integrating within the build process. In practice, the vast majority of our customers take the simpler route and just download and serve the files directly, leaving out optimizations like minification and bundling.

Proposal

We want to extend the support in the SDK for building and publishing Blazor apps so that they can be further processed by other JS toolchains. This includes consuming the blazor app as an NPM package or a node module within the same workspace of a JS app. To this effect, we want to: #53215

  • Extend our build and publish processes to optionally place (symlink) the build outputs into the dist folder.

  • Define a "Blazor" package.json that we can ship as an item template to describe the outputs from a Blazor build.

    • Describe the entry points to the Blazor app in the dist folder.
    • Define different entry points for development and production.
    • Honor the "mode" parameter to determine which entry point to use (see module exports).
    • Define scripts that make it easy to integrate within the npm ecosystem. e.g. npm run build that we will use to call build and publish depending on the mode.
  • Generate modern JS outputs that can be consumed by other JS toolchains. [Blazor] Modernize our Blazor JS assets and their delivery mechanism. #53214

    • Generate ES module bundles that can be consumed via import statements.
    • Break the output into multiple chunks that can be loaded on demand.
    • Update the wasm loading strategy to rely on standard JS idioms that toolchains can understand with enough flexibility to adapt to different bundlers.
      • Standard import. E.g. import { Blazor } from 'blazor'
      • Import as URL. E.g. import system from './_framework/system.wasm?url' (then we do fetch(system.url) or similar to load the asset).
      • Fetch (we don't include an import, and inside the loader we use fetch directly to load the asset).
  • Provide a hook in the SDK to easily run a command to post-process the build outputs and pick up the final static web assets (we somewhat already have this, so we might be able to tweak/reuse it).

  • Provide samples for integrating Blazor with other JS frameworks.

    • Provide samples for integrating Blazor with React, Angular, Vue, etc.
  • Provide samples for post-processing the output with popular JS toolchains.

    • Provide samples for integrating Blazor with vite, rollup, etc. to generate a single bundle.
  • Replace webpack with a more modern bundler/toolchain in the Web.JS project (vite is a good candidate).

  • Introduce unit tests using Jest.

  • Breakdown the Blazor JS code into multiple chunks that can be loaded on demand. [Blazor] Modernize our Blazor JS assets and their delivery mechanism. #53214

    • Blazor web will have a base layer and separate chunks for enhanced nav, server interactivity, and wasm interactivity.
    • Other Blazor flavors will be a single bundle.
  • Refactor and clean up the JS codebase, dedup code, clean up the implementations, add unit tests in JS.

  • Migrate to use esproj for the JS codebase.

    • This will allow us to build the JS from within VS, run unit tests, etc. without having to leave the UI. Assets from the esproj output can be consumed as static web assets by referencing projects, so we can get rid of our custom MSBuild infrastructure.
@ghost ghost added the area-blazor Includes: Blazor, Razor Components label Dec 14, 2023
@mkArtakMSFT mkArtakMSFT added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Dec 18, 2023
@ghost
Copy link

ghost commented Dec 18, 2023

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@javiercn
Copy link
Member Author

#52965

@javiercn
Copy link
Member Author

#53214
#53215

@javiercn javiercn reopened this Jan 23, 2024
@mkArtakMSFT
Copy link
Contributor

Closing as this has been broken down already

@mkArtakMSFT mkArtakMSFT closed this as not planned Won't fix, can't repro, duplicate, stale Jan 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one Pillar: Technical Debt
Projects
None yet
Development

No branches or pull requests

2 participants