Skip to content

Commit 03a1188

Browse files
committed
fix: Restore offline PWA support
1 parent 69dd0ea commit 03a1188

File tree

4 files changed

+107
-13
lines changed

4 files changed

+107
-13
lines changed

src/Uno.Wasm.Bootstrap/ShellTask.cs

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ public override bool Execute()
161161
GeneratedAOTProfile();
162162
GenerateIndexHtml();
163163
GenerateEmbeddedJs();
164+
RemoveDuplicateAssets();
164165
GenerateConfig();
165166
RemoveDuplicateAssets();
166167
}
@@ -184,7 +185,7 @@ private void RemoveDuplicateAssets()
184185
foreach (var existingAsset in existingAssets)
185186
{
186187
Log.LogMessage(MessageImportance.Low, $"Existing asset to remove [{existingAsset.ItemSpec}]");
187-
}
188+
}
188189

189190
// remove existingAssets from StaticWebContent
190191
StaticWebContent = StaticWebContent
@@ -342,7 +343,29 @@ private void ExtractAdditionalJS()
342343
{
343344
_dependencies.Add(name);
344345

345-
CopyResourceToOutput(name, resource);
346+
if (
347+
// Process the service worker file separately to adjust its contents
348+
source.Name.Name.Equals(GetType().Assembly.GetName().Name, StringComparison.OrdinalIgnoreCase)
349+
&& name.Equals("service-worker.js", StringComparison.OrdinalIgnoreCase))
350+
{
351+
using var resourceStream = resource.GetResourceStream();
352+
using var reader = new StreamReader(resourceStream);
353+
354+
var worker = TouchServiceWorker(reader.ReadToEnd());
355+
var memoryStream = new MemoryStream();
356+
357+
using var writer = new StreamWriter(memoryStream, Encoding.UTF8);
358+
writer.Write(worker);
359+
writer.Flush();
360+
361+
memoryStream.Position = 0;
362+
363+
CopyStreamToOutput(name, memoryStream);
364+
}
365+
else
366+
{
367+
CopyResourceToOutput(name, resource);
368+
}
346369

347370
Log.LogMessage($"Additional JS {name}");
348371
}
@@ -431,6 +454,18 @@ private void CopyResourceToOutput(string name, EmbeddedResource resource)
431454
AddStaticAsset(name, dest);
432455
}
433456

457+
private void CopyStreamToOutput(string name, Stream stream)
458+
{
459+
var dest = Path.Combine(_intermediateAssetsPath, name);
460+
461+
using (var destStream = new FileStream(dest, FileMode.Create, FileAccess.Write))
462+
{
463+
stream.CopyTo(destStream);
464+
}
465+
466+
AddStaticAsset(name, dest);
467+
}
468+
434469
private void AddStaticAsset(string targetPath, string filePath, bool overrideExisting = false)
435470
{
436471
var contentRoot = targetPath.StartsWith(_intermediateAssetsPath)
@@ -539,7 +574,14 @@ private void GenerateConfig()
539574
var config = new StringBuilder();
540575

541576
var enablePWA = !string.IsNullOrEmpty(PWAManifestFile);
542-
//var offlineFiles = enablePWA ? string.Join(", ", GetPWACacheableFiles().Select(f => $"\".{f}\"")) : "";
577+
578+
var sanitizedOfflineFiles = StaticWebContent
579+
.Select(f => f.GetMetadata("Link")
580+
.Replace("\\", "/")
581+
.Replace("wwwroot/", ""))
582+
.Concat([$"uno-config.js", "_framework/blazor.boot.json", "."]);
583+
584+
var offlineFiles = enablePWA ? string.Join(", ", sanitizedOfflineFiles.Select(f => $"\"{WebAppBasePath}{f}\"")) : "";
543585

544586
var emccExportedRuntimeMethodsParams = string.Join(
545587
",",
@@ -564,7 +606,7 @@ private void GenerateConfig()
564606
config.AppendLine($"config.uno_dependencies = [{dependencies}];");
565607
config.AppendLine($"config.uno_runtime_options = [{runtimeOptionsSet}];");
566608
config.AppendLine($"config.enable_pwa = {enablePWA.ToString().ToLowerInvariant()};");
567-
//config.AppendLine($"config.offline_files = ['{WebAppBasePath}', {offlineFiles}];");
609+
config.AppendLine($"config.offline_files = ['{WebAppBasePath}', {offlineFiles}];");
568610
config.AppendLine($"config.uno_shell_mode = \"{_shellMode}\";");
569611
config.AppendLine($"config.uno_debugging_enabled = {(!Optimize).ToString().ToLowerInvariant()};");
570612
config.AppendLine($"config.uno_enable_tracing = {EnableTracing.ToString().ToLowerInvariant()};");
@@ -686,8 +728,7 @@ private void GeneratePWAContent(StringBuilder extraBuilder)
686728

687729
extraBuilder.AppendLine($"<link rel=\"manifest\" href=\"$(WEB_MANIFEST)\" />");
688730

689-
// See https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html
690-
extraBuilder.AppendLine($"<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">");
731+
extraBuilder.AppendLine($"<meta name=\"mobile-web-app-capable\" content=\"yes\">");
691732

692733
if (manifestDocument["icons"] is JArray array
693734
&& array.Where(v => v["sizes"]?.Value<string>() == "1024x1024").FirstOrDefault() is JToken img)
@@ -720,7 +761,11 @@ string s when s.StartsWith("./") => $"{WebAppBasePath}/" + s.Substring(2),
720761
}
721762
}
722763

723-
AddStaticAsset(Path.GetFileName(PWAManifestFile), PWAManifestFile!);
764+
var pwaManifestFileName = Path.GetFileName(PWAManifestFile);
765+
var pwaManifestOutputPath = Path.Combine(_intermediateAssetsPath, pwaManifestFileName);
766+
File.WriteAllText(pwaManifestOutputPath, manifestDocument.ToString());
767+
768+
AddStaticAsset(Path.GetFileName(PWAManifestFile), pwaManifestOutputPath);
724769
}
725770
}
726771

@@ -860,6 +905,14 @@ private void GenerateEmbeddedJs()
860905
AddStaticAsset("index.html", htmlPath);
861906
}
862907

908+
private string TouchServiceWorker(string workerBody)
909+
{
910+
workerBody = workerBody.Replace("$(CACHE_KEY)", Guid.NewGuid().ToString());
911+
workerBody = workerBody.Replace("$(REMOTE_WEBAPP_PATH)", WebAppBasePath);
912+
913+
return workerBody;
914+
}
915+
863916
private string TryConvertLongPath(string path)
864917
=> Environment.OSVersion.Platform == PlatformID.Win32NT
865918
&& !string.IsNullOrEmpty(path)

src/Uno.Wasm.Bootstrap/WasmScripts/service-worker.js

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { config } from "$(REMOTE_WEBAPP_PATH)$(REMOTE_BASE_PATH)/uno-config.js";
1+
import { config as unoConfig } from "$(REMOTE_WEBAPP_PATH)uno-config.js";
22

3-
if (config.environmentVariables["UNO_BOOTSTRAP_DEBUGGER_ENABLED"] !== "True") {
3+
4+
if (unoConfig.environmentVariables["UNO_BOOTSTRAP_DEBUGGER_ENABLED"] !== "True") {
45
console.debug("[ServiceWorker] Initializing");
6+
let uno_enable_tracing = unoConfig.uno_enable_tracing;
57

68
self.addEventListener('install', function (e) {
79
console.debug('[ServiceWorker] Installing offline worker');
@@ -11,14 +13,47 @@ if (config.environmentVariables["UNO_BOOTSTRAP_DEBUGGER_ENABLED"] !== "True") {
1113

1214
// Add files one by one to avoid failed downloads to prevent the
1315
// worker to fail installing.
14-
for (var i = 0; i < config.offline_files.length; i++) {
16+
for (var i = 0; i < unoConfig.offline_files.length; i++) {
1517
try {
16-
await cache.add(config.offline_files[i]);
18+
if (uno_enable_tracing) {
19+
console.debug(`[ServiceWorker] cache ${key}`);
20+
}
21+
22+
await cache.add(unoConfig.offline_files[i]);
1723
}
1824
catch (e) {
19-
console.debug(`[ServiceWorker] Failed to fetch ${config.offline_files[i]}`);
25+
console.debug(`[ServiceWorker] Failed to fetch ${unoConfig.offline_files[i]}`);
2026
}
2127
}
28+
29+
// Add the runtime's own files to the cache. We cannot use the
30+
// existing cached content from the runtime as the keys contain a
31+
// hash we cannot reliably compute.
32+
var c = await fetch("$(REMOTE_WEBAPP_PATH)_framework/blazor.boot.json");
33+
const monoConfigResources = (await c.json()).resources;
34+
35+
var entries = {
36+
...(monoConfigResources.coreAssembly || {})
37+
, ...(monoConfigResources.assembly || {})
38+
, ...(monoConfigResources.lazyAssembly || {})
39+
, ...(monoConfigResources.jsModuleWorker || {})
40+
, ...(monoConfigResources.jsModuleGlobalization || {})
41+
, ...(monoConfigResources.jsModuleNative || {})
42+
, ...(monoConfigResources.jsModuleRuntime || {})
43+
, ...(monoConfigResources.wasmNative || {})
44+
, ...(monoConfigResources.icu || {})
45+
, ...(monoConfigResources.coreAssembly || {})
46+
};
47+
48+
for (var key in entries) {
49+
var uri = `$(REMOTE_WEBAPP_PATH)_framework/${key}`;
50+
51+
if (uno_enable_tracing) {
52+
console.debug(`[ServiceWorker] cache ${uri}`);
53+
}
54+
55+
await cache.add(uri);
56+
}
2257
})
2358
);
2459
});

src/Uno.Wasm.Sample.RayTracer/Uno.Wasm.Sample.RayTracer.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<WasmShellMonoRuntimeExecutionMode Condition="'$(UseAOT)'=='true'">InterpreterAndAOT</WasmShellMonoRuntimeExecutionMode>
99
<MonoRuntimeDebuggerEnabled Condition="'$(Configuration)'=='Debug'">true</MonoRuntimeDebuggerEnabled>
1010
<DefineConstants>$(DefineConstants);__WASM__;UWP</DefineConstants>
11-
<WasmPWAManifestFile>manifest.json</WasmPWAManifestFile>
11+
<WasmPWAManifestFile>app.webmanifest</WasmPWAManifestFile>
1212
<!--<WasmShellEnableEmccProfiling>true</WasmShellEnableEmccProfiling>-->
1313
<WasmShellPrintAOTSkippedMethods>true</WasmShellPrintAOTSkippedMethods>
1414
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
@@ -25,6 +25,12 @@
2525

2626
<Import Project="..\Uno.Wasm.Bootstrap\build\Uno.Wasm.Bootstrap.props" />
2727
<Import Project="..\Uno.Wasm.Bootstrap\build\Uno.Wasm.Bootstrap.targets" />
28+
<ItemGroup>
29+
<None Remove="app.webmanifest" />
30+
</ItemGroup>
31+
<ItemGroup>
32+
<Content Include="app.webmanifest" />
33+
</ItemGroup>
2834

2935
<ItemGroup>
3036
<LinkerDescriptor Include="LinkerConfig.xml" />
File renamed without changes.

0 commit comments

Comments
 (0)