Soenneker.Blazor.Utils.ModuleImport
4.0.1869
Prefix Reserved
dotnet add package Soenneker.Blazor.Utils.ModuleImport --version 4.0.1869
NuGet\Install-Package Soenneker.Blazor.Utils.ModuleImport -Version 4.0.1869
<PackageReference Include="Soenneker.Blazor.Utils.ModuleImport" Version="4.0.1869" />
<PackageVersion Include="Soenneker.Blazor.Utils.ModuleImport" Version="4.0.1869" />
<PackageReference Include="Soenneker.Blazor.Utils.ModuleImport" />
paket add Soenneker.Blazor.Utils.ModuleImport --version 4.0.1869
#r "nuget: Soenneker.Blazor.Utils.ModuleImport, 4.0.1869"
#:package Soenneker.Blazor.Utils.ModuleImport@4.0.1869
#addin nuget:?package=Soenneker.Blazor.Utils.ModuleImport&version=4.0.1869
#tool nuget:?package=Soenneker.Blazor.Utils.ModuleImport&version=4.0.1869
Soenneker.Blazor.Utils.ModuleImport
A scoped Blazor utility for dynamically importing and reusing JavaScript ES module references.
It supports relative application/static-web-asset modules and absolute HTTP(S) modules. Concurrent callers for the same normalized location share one cached import.
Installation
dotnet add package Soenneker.Blazor.Utils.ModuleImport
using Soenneker.Blazor.Utils.ModuleImport.Registrars;
builder.Services.AddModuleImportUtilAsScoped();
Inject IModuleImportUtil into an interop service. Module imports require an interactive browser renderer and cannot run during server prerendering.
Import an application module
For a file at wwwroot/js/orders.js:
export function formatOrderNumber(value) {
return `ORD-${value}`;
}
using Microsoft.JSInterop;
using Soenneker.Blazor.Utils.ModuleImport.Abstract;
public sealed class OrdersInterop(IModuleImportUtil modules)
{
private const string ModulePath = "/js/orders.js";
public async ValueTask<string> Format(
int value,
CancellationToken cancellationToken = default)
{
IJSObjectReference module =
await modules.GetContentModuleReference(ModulePath, cancellationToken);
return await module.InvokeAsync<string>(
"formatOrderNumber",
cancellationToken,
value);
}
}
For a Razor class library static asset, use its _content URL:
const string ModulePath =
"_content/Example.Components/js/widget.js";
Leading /, ./, or no prefix normalize to the same relative import URL. Backslashes, absolute URLs, and parent (..) path segments are rejected by the content-module APIs.
Import an external module
IJSObjectReference module =
await modules.GetExternalModuleReference(
"https://cdn.example.com/library/4.2.0/index.js",
cancellationToken);
External imports accept only absolute HTTP or HTTPS URLs. The remote server must allow module loading under browser CORS rules, and the application’s Content Security Policy must permit the source.
Dynamic import() does not provide Subresource Integrity through this API. Pin an immutable version, trust the host, and never accept a module URL from user input. A remotely imported module executes code in the page and is part of the application’s supply chain.
Module items
Most callers should use the reference methods. GetContentModule and GetExternalModule return a ModuleImportItem after loading succeeds:
ModuleImportItem item = await modules.GetContentModule(ModulePath);
IJSObjectReference module = item.ScriptReference!;
Loaded is already complete when these methods return and remains available for compatibility. The item’s completion source and reference setter are controlled by the library.
Failed or cancelled imports are evicted from the utility cache, allowing a later call to retry. Cancellation stops the .NET caller from waiting, but the browser may already have fetched or evaluated part of the module.
Ownership and disposal
The utility owns cached ModuleImportItem and IJSObjectReference instances. Consumers should not dispose returned items or references directly.
Remove one cached handle when its owner is finished and no other consumer in the same scope uses it:
bool removed = await modules.DisposeContentModule(ModulePath);
bool removed = await modules.DisposeExternalModule(externalUrl);
Disposal removes and releases the cached Blazor reference. It does not unload JavaScript code from the browser or guarantee that a later dynamic import re-evaluates the module; browsers cache ES modules by resolved URL, so module-level state can persist.
The registry is scoped. In Blazor Server that normally means a circuit; in WebAssembly it normally means the application. Remaining references are disposed with the scope.
Do not evict a module while another consumer is invoking it. If multiple services share a module, let the scope own its lifetime or coordinate a single owner instead of disposing it from each consumer.
Module paths and export names should be trusted application constants. Values returned by JavaScript are still untrusted input and require validation before privileged use.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.JSInterop (>= 10.0.11)
- Soenneker.Dictionaries.Singletons (>= 4.0.87)
- Soenneker.Extensions.CancellationTokens (>= 4.0.24)
- Soenneker.Utils.CancellationScopes (>= 4.0.52)
NuGet packages (16)
Showing the top 5 NuGet packages that depend on Soenneker.Blazor.Utils.ModuleImport:
| Package | Downloads |
|---|---|
|
Soenneker.Blazor.Utils.JsVariable
A Blazor interop library that checks (and waits) for the existence of a JS variable |
|
|
Soenneker.Blazor.Clarity
A small Blazor interop library that sets up Microsoft Clarity |
|
|
Soenneker.Blazor.LogJson
A Blazor interop library that logs JSON (like HTTP requests/responses) within the browser |
|
|
Soenneker.Blazor.ApplicationInsights
A Blazor interop library that sets up client-side Application Insights |
|
|
Soenneker.Blazor.MediaQuery
A Blazor interop library for media queries for viewport size logic |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.1869 | 0 | 8/30/2026 |
| 4.0.1868 | 0 | 8/30/2026 |
| 4.0.1866 | 117 | 8/30/2026 |
| 4.0.1865 | 74 | 8/30/2026 |
| 4.0.1864 | 86 | 8/30/2026 |
| 4.0.1861 | 100 | 8/29/2026 |
| 4.0.1860 | 35 | 8/29/2026 |
| 4.0.1859 | 560 | 8/29/2026 |
| 4.0.1858 | 3,099 | 8/26/2026 |
| 4.0.1857 | 780 | 8/26/2026 |
| 4.0.1856 | 3,589 | 8/21/2026 |
| 4.0.1855 | 3,663 | 8/18/2026 |
| 4.0.1854 | 2,777 | 8/13/2026 |
| 4.0.1853 | 1,040 | 8/11/2026 |
| 4.0.1852 | 7,733 | 8/9/2026 |
| 4.0.1851 | 2,312 | 8/8/2026 |
| 4.0.1850 | 1,431 | 8/8/2026 |
| 4.0.1849 | 4,502 | 8/7/2026 |
| 4.0.1848 | 3,495 | 7/29/2026 |
| 4.0.1847 | 3,214 | 7/29/2026 |
Update dependency Soenneker.Utils.CancellationScopes to 4.0.52 (#2418)