Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"dotnet-serve": {
"version": "1.10.193",
"version": "1.10.194",
"commands": [
"dotnet-serve"
],
Expand Down
11 changes: 8 additions & 3 deletions eng/IndexHtmlGeneration.targets
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

<PropertyGroup>
<IndexHtmlTemplatePath Condition="'$(IndexHtmlTemplatePath)' == ''">$(MSBuildThisFileDirectory)index.template.html</IndexHtmlTemplatePath>
<IndexHtmlOutputPath Condition="'$(IndexHtmlOutputPath)' == ''">$(MSBuildProjectDirectory)\wwwroot\index.html</IndexHtmlOutputPath>
<IndexHtmlOutputRelativePath Condition="'$(IndexHtmlOutputRelativePath)' == ''">wwwroot\index.html</IndexHtmlOutputRelativePath>
<IndexHtmlOutputPath Condition="'$(IndexHtmlOutputPath)' == ''">$(MSBuildProjectDirectory)\$(IndexHtmlOutputRelativePath)</IndexHtmlOutputPath>
<IndexHtmlScriptPath Condition="'$(IndexHtmlScriptPath)' == ''">_framework/blazor.js</IndexHtmlScriptPath>
<IndexHtmlGoatcounterPath Condition="'$(IndexHtmlGoatcounterPath)' == ''">/</IndexHtmlGoatcounterPath>
<!--
Expand All @@ -13,10 +14,14 @@
</PropertyGroup>

<ItemGroup>
<!-- Mark as Content so it's included in `service-worker-assets.js`. -->
<!--
Mark as Content so it's included in `service-worker-assets.js`.
The relative path is used so that `DefineStaticWebAssets` in the SDK can match it
against the `wwwroot/**` pattern (absolute paths are rejected by that pattern).
-->
<None Remove="$(IndexHtmlOutputPath)" />
<Content Remove="$(IndexHtmlOutputPath)" />
<Content Include="$(IndexHtmlOutputPath)" CopyToPublishDirectory="PreserveNewest" />
<Content Include="$(IndexHtmlOutputRelativePath)" CopyToPublishDirectory="PreserveNewest" />

<UpToDateCheckBuilt Include="$(IndexHtmlOutputPath)" Original="$(IndexHtmlTemplatePath)" />
</ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions eng/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ chmod +x dotnet-install.sh
./dotnet/dotnet --version
./dotnet/dotnet workload install wasm-tools wasm-experimental
./dotnet/dotnet publish -o output src/WebAssembly
./dotnet/dotnet run --file eng/check-publish-output.cs -- output
40 changes: 40 additions & 0 deletions eng/check-publish-output.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env dotnet

using System.Text.Json.Nodes;

if (args is not [{ Length: > 0 } arg])
{
Console.Error.WriteLine("Usage: check-publish-output.cs <path to publish output directory>");
return 1;
}

if (!Directory.Exists(arg))
{
Console.Error.WriteLine($"Error: Directory '{arg}' does not exist.");
return 1;
}

var serviceWorkerAssetsFile = Path.Join(arg, "wwwroot", "service-worker-assets.js");
if (!File.Exists(serviceWorkerAssetsFile))
{
Console.Error.WriteLine($"Error: Service worker assets file not found at '{serviceWorkerAssetsFile}'.");
return 1;
}

var serviceWorkerAssetsContent = File.ReadAllText(serviceWorkerAssetsFile);
const string prefix = "self.assetsManifest = ";
if (!serviceWorkerAssetsContent.StartsWith(prefix, StringComparison.Ordinal))
{
Console.Error.WriteLine($"Error: Unexpected content in service worker assets file. Expected it to start with '{prefix}'.");
return 1;
}

var serviceWorkerAssetsJson = serviceWorkerAssetsContent[prefix.Length..].TrimEnd(';', ' ', '\r', '\n');
if (JsonNode.Parse(serviceWorkerAssetsJson)!["assets"]!.AsArray().SingleOrDefault(a => a!["url"]!.GetValue<string>() == "index.html") == null)
{
Console.Error.WriteLine("Error: index.html is not listed in the service worker assets manifest.");
return 1;
}

Console.Error.WriteLine("OK: index.html is listed in the service worker assets manifest.");
Comment thread
jjonescz marked this conversation as resolved.
return 0;
2 changes: 1 addition & 1 deletion src/WebAssembly/WebAssembly.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<IndexHtmlScripts><script>navigator.serviceWorker.register('service-worker.js');</script></IndexHtmlScripts>
<IndexHtmlLoadingInfoFooter>
<div style="margin-top: 1em">
For faster loading, use the
Consider using more capable and performant
<a href="https://apps.microsoft.com/detail/9PCPMM329DZT" target="_blank">
<!-- https://upload.wikimedia.org/wikipedia/commons/a/a7/Microsoft_Store.svg -->
<svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 1794.1 1782.3" style="height: 1em; margin: 0 0.25em 0 0.25em">
Expand Down
50 changes: 28 additions & 22 deletions src/WebAssembly/wwwroot/service-worker.published.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const offlineAssetsExclude = [ /^service-worker\.js$/ ];
// Replace with your base path if you are hosting on a subfolder. Ensure there is a trailing '/'.
const base = "/";
const baseUrl = new URL(base, self.origin);
const manifestUrlList = self.assetsManifest.assets.map(asset => new URL(asset.url, baseUrl).href);
const manifestUrlSet = new Set(self.assetsManifest.assets.map(asset => new URL(asset.url, baseUrl).href));

async function onInstall() {
console.info('Service worker: Install');
Expand Down Expand Up @@ -80,31 +80,37 @@ async function onFetch(event) {
return new Response('', { headers: { Refresh: '0' } });
}

let cachedResponse = null;
if (event.request.method === 'GET') {
// For all navigation requests, try to serve index.html from cache,
// unless that request is for an offline resource.
// If you need some URLs to be server-rendered, edit the following check to exclude those URLs
const shouldServeIndexHtml = event.request.mode === 'navigate'
&& !manifestUrlList.some(url => url === event.request.url);

if (shouldServeIndexHtml) {
console.debug(`Service worker: serving index.html for ${event.request.url}`);
const fetchResponse = fetch(event.request);
try {
// First try network / disk cache (it's usually faster than the service worker cache).
return await fetchResponse;
} catch {
Comment thread
jjonescz marked this conversation as resolved.
let cachedResponse = null;
if (event.request.method === 'GET') {
// For all navigation requests, try to serve index.html from cache,
// unless that request is for an offline resource.
// If you need some URLs to be server-rendered, edit the following check to exclude those URLs
const shouldServeIndexHtml = event.request.mode === 'navigate'
&& !manifestUrlSet.has(event.request.url);

if (shouldServeIndexHtml) {
console.debug(`Service worker: serving index.html for ${event.request.url}`);
}

const request = shouldServeIndexHtml ? 'index.html' : event.request;

const cache = await caches.open(cacheName);
// We ignore search query (so our pre-cached `app.css` matches request `app.css?v=2`),
// we have pre-cached the latest versions of all static assets anyway.
cachedResponse = await cache.match(request, { ignoreSearch: true });
}

const request = shouldServeIndexHtml ? 'index.html' : event.request;

const cache = await caches.open(cacheName);
// We ignore search query (so our pre-cached `app.css` matches request `app.css?v=2`),
// we have pre-cached the latest versions of all static assets anyway.
cachedResponse = await cache.match(request, { ignoreSearch: true });
}
if (!cachedResponse) {
console.debug(`Service worker: cache miss for ${event.request.url}`);
}

if (!cachedResponse) {
console.debug(`Service worker: cache miss for ${event.request.url}`);
return cachedResponse || fetchResponse;
Comment thread
jjonescz marked this conversation as resolved.
}

return cachedResponse || fetch(event.request);
}

/**
Expand Down