Substantive.Blazor.JSInterop 9.4.0-build20260114r3
Substantive.Blazor.JSInterop
Utilities for bridging .NET and browser APIs in Blazor applications. The library ships a set of opinionated services that simplify dynamically loading JavaScript, CSS, and other assets at runtime while keeping Blazor Server and Blazor WebAssembly hosting models in sync.
Why this library?
- Consistent DOM loading –
IDomFileInjectorabstracts both JSHost (WASM) andIJSRuntime(Server) pipelines, so component code stays identical regardless of where it runs. - Security-first defaults – optional attributes (
integrity,crossorigin,referrerpolicy,nonce,fetchpriority) map directly to the generated DOM nodes, reducing CSP and mixed-content regressions. - Tenant/feature isolation – scripts, styles, or media can be injected when a component activates and removed when it disposes, minimizing bundle size and side effects.
- Deterministic cleanup – optional
tagidentifiers let you remove previously injected assets without tracking the original URIs, which is useful for multi-tenant layouts and dynamic feature toggles. - Typed interop surface – TypeScript helpers (
wwwroot/src/DynamicFileLoader.ts) and the bundled JS deliver a narrowly scoped API focused on asset management.
Getting started
Reference the project/package from your Blazor application.
Register the injector for the current hosting model in
Program.cs:if (OperatingSystem.IsBrowser()) { builder.Services.AddSingleton<IDomFileInjector, DomFileInjectorJSHost>(); } else { builder.Services.AddSingleton<IDomFileInjector, DomFileInjectorJSRuntime>(); }Inject and use the service inside a component:
@inject IDomFileInjector DomFileInjector @implements IAsyncDisposable protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await DomFileInjector.LoadJavaScriptFileAsync( scriptSrc: "https://cdn.example.com/widgets.js", scriptType: "module", integrity: "sha384-...", crossOrigin: "anonymous", referrerPolicy: "strict-origin-when-cross-origin", nonce: cspNonceFromServer, fetchPriority: "high", tag: "widgets-lib"); await DomFileInjector.LoadCSSFileAsync( src: "https://cdn.example.com/widgets.css", media: "(min-width: 768px)", tag: "widgets-style"); } } public async ValueTask DisposeAsync() { await DomFileInjector.UnloadJavaScriptFileByTagAsync("widgets-lib"); await DomFileInjector.UnloadCSSFileByTagAsync("widgets-style"); }
Features
| Area | Description | |
|---|---|---|
| - | JavaScript loader | Inject/remove <script> tags with async/defer, SRI, module/nomodule, nonce, and fetchpriority support. |
| - | CSS loader | Inject/remove <link rel="stylesheet"> with integrity, crossorigin, media queries, nonce, and fetchpriority. |
| + | JavaScript loader | Inject/remove <script> tags with async/defer, SRI, module/nomodule, nonce, fetchpriority, and optional tag identifiers for deterministic cleanup. |
| + | CSS loader | Inject/remove <link rel="stylesheet"> with integrity, crossorigin, media queries, nonce, fetchpriority, and optional tags for group removal. |
| Asset loader | Preload fonts/images/videos or generic assets with the same security attributes. | |
| TypeScript tooling | Source files live under wwwroot/src and are bundled to wwwroot/dist. Update TS, then rebuild to refresh the bundle. |
Development workflow
Edit TypeScript in
wwwroot/src.Bundle using the repo’s configured bundler (Rspack). Running
dotnet buildregenerateswwwroot/dist/js/DynamicFileLoader.bundle.jsvia the existing targets.Run tests/build from the repo root:
dotnet build
Tag-based unloading cheat sheet
| Scenario | Recommended call |
|---|---|
| Remove a single script by URL | UnloadJavaScriptFileAsync("https://cdn.example.com/widgets.js") |
| Remove any script that was loaded with a specific identifier | UnloadJavaScriptFileByTagAsync("widgets-lib") |
| Remove a single stylesheet by URL | UnloadCSSFileAsync("https://cdn.example.com/widgets.css") |
| Remove any stylesheet loaded with a specific identifier | UnloadCSSFileByTagAsync("widgets-style") |
Showing the top 20 packages that depend on Substantive.Blazor.JSInterop.
| Packages | Downloads |
|---|---|
|
Substantive.Blazor.Captcha
Blazor components for display and validate Captcha widgets.
|
4 |
|
Substantive.Blazor.Captcha
Blazor components for display and validate Captcha widgets.
|
5 |
|
Substantive.Blazor.Experimental
A collection of Blazor experimental components and services.
|
5 |
|
Substantive.Blazor.Markdown
Library for parsing and linting markdown content.
|
5 |
|
Substantive.Blazor.Markdown
Library for parsing and linting markdown content.
|
6 |
|
Substantive.Blazor.Markdown
Library for parsing and linting markdown content.
|
23 |
|
Substantive.Blazor.Markdown
Library for parsing and linting markdown content.
|
24 |
|
Substantive.Blazor.MediaPlayer
Blazor components for video and audio player.
|
4 |
|
Substantive.Blazor.MediaPlayer
Blazor components for video and audio player.
|
5 |
|
Substantive.Blazor.WebEmbedded
Blazor components for embedded a web page or content via iFrame.
|
5 |
|
Substantive.Blazor.WebStorages
Services for maniuplate Cookie, LocalStorage, and SessionStorage.
|
4 |
|
Substantive.Blazor.WebStorages
Services for maniuplate Cookie, LocalStorage, and SessionStorage.
|
12 |
|
Substantive.Blazor.WebStorages
Services for maniuplate Cookie, LocalStorage, and SessionStorage.
|
17 |
|
Substantive.Blazor.WebStorages
Services for maniuplate Cookie, LocalStorage, and SessionStorage.
|
24 |
|
Substantive.Metapackage.Blazor
A metapackage contains all Blazor essential building blocks. It packed standalone Blazor components and extensions that often use such as JSInterop, BrowserInterop, Navigation, Exception Handling, Localization, etc,.
|
10 |
|
Substantive.SubstantiveBlazor.Core
The Substantive Design System's core library. This package manages UI libraries that the Design System builds upon.
|
22 |
|
Substantive.SubstantiveBlazor.Core
The Substantive Design System's core library. This package manages UI libraries that the Design System builds upon.
|
24 |
.NET 10.0
- Microsoft.AspNetCore.Components.Web (>= 10.0.2)