Skip to content

Commit 132e07c

Browse files
committed
Added support for running in module mode instead of classic mode, including in ServiceWorkers where module mode requires static imports.
1 parent dceb180 commit 132e07c

11 files changed

Lines changed: 630 additions & 170 deletions
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using SpawnDev.BlazorJS.JSObjects;
2+
3+
namespace SpawnDev.BlazorJS.WebWorkers
4+
{
5+
/// <summary>
6+
/// Options used for CreateWebWorker
7+
/// </summary>
8+
public class SharedWebWorkerOptions
9+
{
10+
/// <summary>
11+
/// WorkerOptions
12+
/// </summary>
13+
public SharedWorkerOptions? WorkerOptions { get; set; }
14+
/// <summary>
15+
/// The URL to the worker script to load.<br/>
16+
/// Defaults to:
17+
/// module - "spawndev.blazorjs.webworkers.module.js"<br/>
18+
/// classic - "spawndev.blazorjs.webworkers.js"<br/>
19+
/// </summary>
20+
public string? ScriptUrl { get; set; } = null;
21+
/// <summary>
22+
/// Additional query parameters to add to the worker script URL.<br/>
23+
/// </summary>
24+
public Dictionary<string, string>? QueryParams { get; set; } = null;
25+
}
26+
}

SpawnDev.BlazorJS.WebWorkers/SpawnDev.BlazorJS.WebWorkers.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,17 @@
8383
</ItemGroup>
8484

8585
<ItemGroup>
86-
<PackageReference Include="SpawnDev.BlazorJS" Version="2.20.0" />
86+
<PackageReference Include="SpawnDev.BlazorJS" Version="2.21.0" />
8787
</ItemGroup>
8888

8989
<ItemGroup>
9090
<SupportedPlatform Include="browser" />
9191
</ItemGroup>
9292

93+
<PropertyGroup>
94+
<!-- Disable filename mangling with hash which is enabled by default in .Net 10 SDK. It causes runtime loading of Javascript files to fail due to unknown filename. -->
95+
<StaticWebAssetFingerprintingEnabled>false</StaticWebAssetFingerprintingEnabled>
96+
<StaticWebAssetsFingerprintContent>false</StaticWebAssetsFingerprintContent>
97+
</PropertyGroup>
98+
9399
</Project>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using SpawnDev.BlazorJS.JSObjects;
2+
3+
namespace SpawnDev.BlazorJS.WebWorkers
4+
{
5+
/// <summary>
6+
/// Options used for CreateWebWorker
7+
/// </summary>
8+
public class WebWorkerOptions
9+
{
10+
/// <summary>
11+
/// WorkerOptions
12+
/// </summary>
13+
public WorkerOptions? WorkerOptions { get; set; }
14+
/// <summary>
15+
/// The URL to the worker script to load.<br/>
16+
/// Defaults to:
17+
/// module - "spawndev.blazorjs.webworkers.module.js"<br/>
18+
/// classic - "spawndev.blazorjs.webworkers.js"<br/>
19+
/// </summary>
20+
public string? ScriptUrl { get; set; } = null;
21+
/// <summary>
22+
/// Additional query parameters to add to the worker script URL.<br/>
23+
/// </summary>
24+
public Dictionary<string, string>? QueryParams { get; set; } = null;
25+
}
26+
}

SpawnDev.BlazorJS.WebWorkers/WebWorkerService.cs

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Microsoft.AspNetCore.Components;
2-
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
32
using Microsoft.Extensions.DependencyInjection;
43
using SpawnDev.BlazorJS.JSObjects;
54
using SpawnDev.BlazorJS.Toolbox;
@@ -60,6 +59,11 @@ public class WebWorkerService : IDisposable, IAsyncBackgroundService
6059
/// </summary>
6160
public bool InterConnectEnabled { get; set; } = true;
6261
/// <summary>
62+
/// If true, the faux window environment created to allow Blazor to load is cleaned up after the Blazor app has loaded.<br />
63+
/// The default is true for compatibility with other libraries.
64+
/// </summary>
65+
public bool RestoreEnvironment { get; set; } = true;
66+
/// <summary>
6367
/// A ServiceCallDispatcher that executes on this instance
6468
/// </summary>
6569
public ServiceCallDispatcher Local { get; }
@@ -96,6 +100,10 @@ public class WebWorkerService : IDisposable, IAsyncBackgroundService
96100
/// </summary>
97101
public string WebWorkerJSScript { get; } = "spawndev.blazorjs.webworkers.js";
98102
/// <summary>
103+
/// The script location used for new module worker instances
104+
/// </summary>
105+
public string WebWorkerModuleJSScript { get; } = "spawndev.blazorjs.webworkers.module.js";
106+
/// <summary>
99107
/// The script used for instance interconnect shared worker instance (if used)
100108
/// </summary>
101109
public string WebWorkerInterconnectJSScript { get; } = "spawndev.blazorjs.webworkers.interconnect.js";
@@ -171,11 +179,12 @@ public WebWorkerService(IWebAssemblyServices webAssemblyServices, BlazorJSRuntim
171179
WebWorkerSupported = !JS.IsUndefined("Worker");
172180
SharedWebWorkerSupported = !JS.IsUndefined("SharedWorker");
173181
ServiceWorkerSupported = !JS.IsUndefined("ServiceWorkerRegistration");
174-
AppBaseUri = JS.Get<string>("document.baseURI");
182+
AppBaseUri = JS.Get<string?>("document?.baseURI") ?? JS.Get<string>("documentBaseURI");
175183
var locationHref = JS.Get<string>("location.href");
176184
var locationUri = new Uri(locationHref);
177185
var workerScriptUri = new Uri(new Uri(AppBaseUri), WebWorkerJSScript);
178186
WebWorkerJSScript = workerScriptUri.ToString();
187+
WebWorkerModuleJSScript = new Uri(new Uri(AppBaseUri), WebWorkerModuleJSScript).ToString();
179188
Locks = JS.Get<LockManager>("navigator.locks");
180189
LockManagerSupported = Locks != null;
181190
var queryParams = HttpUtility.ParseQueryString(locationUri.Query);
@@ -192,6 +201,11 @@ public WebWorkerService(IWebAssemblyServices webAssemblyServices, BlazorJSRuntim
192201
// remove the instanceOwnerIdKey attribute from the url
193202
NavigationManager.NavigateTo(newPath, false, true);
194203
}
204+
if (RestoreEnvironment && !JS.IsWindow)
205+
{
206+
JS.Delete("window");
207+
JS.Delete("document");
208+
}
195209
Info = new AppInstanceInfo
196210
{
197211
OwnerId = instanceOwnerId,
@@ -672,9 +686,10 @@ public async Task RegisterServiceWorker()
672686
{
673687
if (JS.WindowThis != null)
674688
{
689+
var workerMode = ServiceWorkerConfig.Options?.Type;
675690
if (string.IsNullOrEmpty(ServiceWorkerConfig.ScriptURL))
676691
{
677-
ServiceWorkerConfig.ScriptURL = WebWorkerJSScript;
692+
ServiceWorkerConfig.ScriptURL = workerMode == "module" ? WebWorkerModuleJSScript : WebWorkerJSScript;
678693
}
679694
var kvps = new Dictionary<string, string>();
680695
if (ServiceWorkerConfig.ImportServiceWorkerAssets)
@@ -792,6 +807,68 @@ public async Task<bool> UnregisterServiceWorker()
792807
var webWorker = new WebWorker(worker, WebAssemblyServices);
793808
return webWorker;
794809
}
810+
811+
public async Task<WebWorker?> GetWebWorker(WebWorkerOptions webWorkerOptions)
812+
{
813+
var webWorker = GetWebWorkerSync(webWorkerOptions);
814+
if (webWorker == null) return null;
815+
await webWorker.WhenReady;
816+
return webWorker;
817+
}
818+
819+
public WebWorker? GetWebWorkerSync(WebWorkerOptions webWorkerOptions)
820+
{
821+
if (!WebWorkerSupported) return null;
822+
webWorkerOptions ??= new WebWorkerOptions();
823+
webWorkerOptions.WorkerOptions ??= new WorkerOptions();
824+
webWorkerOptions.QueryParams ??= new Dictionary<string, string>();
825+
if (!string.IsNullOrEmpty(WorkerIndexHtml))
826+
{
827+
webWorkerOptions.QueryParams["indexHtml"] = WorkerIndexHtml;
828+
}
829+
if (string.IsNullOrEmpty(webWorkerOptions.ScriptUrl))
830+
{
831+
webWorkerOptions.ScriptUrl = webWorkerOptions.WorkerOptions.Type == "module" ? WebWorkerModuleJSScript : WebWorkerJSScript;
832+
}
833+
if (webWorkerOptions.QueryParams.Count > 0)
834+
{
835+
webWorkerOptions.ScriptUrl += "?" + string.Join('&', webWorkerOptions.QueryParams.Select(o => $"{o.Key}={o.Value}"));
836+
}
837+
var worker = new Worker(webWorkerOptions.ScriptUrl, webWorkerOptions.WorkerOptions);
838+
var webWorker = new WebWorker(worker, WebAssemblyServices);
839+
return webWorker;
840+
}
841+
public async Task<SharedWebWorker?> GetSharedWebWorker(SharedWebWorkerOptions webWorkerOptions)
842+
{
843+
var webWorker = GetSharedWebWorkerSync(webWorkerOptions);
844+
if (webWorker == null) return null;
845+
await webWorker.WhenReady;
846+
return webWorker;
847+
}
848+
public SharedWebWorker? GetSharedWebWorkerSync(SharedWebWorkerOptions webWorkerOptions)
849+
{
850+
if (!WebWorkerSupported) return null;
851+
webWorkerOptions ??= new SharedWebWorkerOptions();
852+
webWorkerOptions.WorkerOptions ??= new SharedWorkerOptions();
853+
webWorkerOptions.QueryParams ??= new Dictionary<string, string>();
854+
if (!string.IsNullOrEmpty(WorkerIndexHtml))
855+
{
856+
webWorkerOptions.QueryParams["indexHtml"] = WorkerIndexHtml;
857+
}
858+
if (string.IsNullOrEmpty(webWorkerOptions.ScriptUrl))
859+
{
860+
webWorkerOptions.ScriptUrl = webWorkerOptions.WorkerOptions.Type == "module" ? WebWorkerModuleJSScript : WebWorkerJSScript;
861+
}
862+
if (webWorkerOptions.QueryParams.Count > 0)
863+
{
864+
webWorkerOptions.ScriptUrl += "?" + string.Join('&', webWorkerOptions.QueryParams.Select(o => $"{o.Key}={o.Value}"));
865+
}
866+
webWorkerOptions.WorkerOptions.Name ??= "";
867+
var worker = new SharedWorker(webWorkerOptions.ScriptUrl, webWorkerOptions.WorkerOptions);
868+
var webWorker = new SharedWebWorker(webWorkerOptions.WorkerOptions.Name, worker, WebAssemblyServices);
869+
return webWorker;
870+
}
871+
795872
/// <summary>
796873
/// Returns a new SharedWebWorker instance. If a SharedWorker already existed by this name SharedWebWorker will be connected to that instance.
797874
/// </summary>

0 commit comments

Comments
 (0)