-
Notifications
You must be signed in to change notification settings - Fork 10.3k
[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
Comments
Thanks for contacting us. We're moving this issue to the |
Closing as this has been broken down already |
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.
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
import { Blazor } from 'blazor'
import system from './_framework/system.wasm?url'
(then we dofetch(system.url)
or similar 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 post-processing the output with popular JS toolchains.
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
Refactor and clean up the JS codebase, dedup code, clean up the implementations, add unit tests in JS.
Migrate to useesproj
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.The text was updated successfully, but these errors were encountered: