Skip to content

Commit 513d10a

Browse files
committed
Generate Link headers based on StaticWebAssets manifest properties
1 parent ab38f49 commit 513d10a

File tree

2 files changed

+120
-3
lines changed

2 files changed

+120
-3
lines changed

src/Components/Endpoints/src/Rendering/EndpointHtmlRenderer.Streaming.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Microsoft.Extensions.DependencyInjection;
1313
using Microsoft.Extensions.Hosting;
1414
using Microsoft.Extensions.Options;
15+
using Microsoft.Extensions.Primitives;
1516

1617
namespace Microsoft.AspNetCore.Components.Endpoints;
1718

@@ -275,6 +276,12 @@ private void WriteComponentHtml(int componentId, TextWriter output, bool allowBo
275276
{
276277
if (_httpContext.RequestServices.GetRequiredService<WebAssemblySettingsEmitter>().TryGetSettingsOnce(out var settings))
277278
{
279+
if (marker.Type is ComponentMarker.WebAssemblyMarkerType)
280+
{
281+
// Preload WebAssembly assets when using WebAssembly (not Auto) mode
282+
AppendWebAssemblyPreloadHeaders();
283+
}
284+
278285
var settingsJson = JsonSerializer.Serialize(settings, ServerComponentSerializationSettings.JsonSerializationOptions);
279286
output.Write($"<!--Blazor-WebAssembly:{settingsJson}-->");
280287
}
@@ -311,6 +318,65 @@ private void WriteComponentHtml(int componentId, TextWriter output, bool allowBo
311318
}
312319
}
313320

321+
private void AppendWebAssemblyPreloadHeaders()
322+
{
323+
var assets = _httpContext.GetEndpoint()?.Metadata.GetMetadata<ResourceAssetCollection>();
324+
if (assets != null)
325+
{
326+
var headers = new List<string>();
327+
foreach (var asset in assets)
328+
{
329+
if (asset.Properties == null)
330+
{
331+
continue;
332+
}
333+
334+
// Use preloadrel to identify assets that should to be preloaded
335+
string? header = null;
336+
foreach (var property in asset.Properties)
337+
{
338+
if (property.Name.Equals("preloadrel", StringComparison.OrdinalIgnoreCase))
339+
{
340+
header = String.Concat($"<{asset.Url}>", "; rel=", property.Value);
341+
break;
342+
}
343+
}
344+
345+
if (header == null)
346+
{
347+
continue;
348+
}
349+
350+
foreach (var property in asset.Properties)
351+
{
352+
if (property.Name.Equals("preloadas", StringComparison.OrdinalIgnoreCase))
353+
{
354+
header = String.Concat(header, "; as=", property.Value);
355+
}
356+
else if (property.Name.Equals("preloadpriority", StringComparison.OrdinalIgnoreCase))
357+
{
358+
header = String.Concat(header, "; fetchpriority=", property.Value);
359+
}
360+
else if (property.Name.Equals("preloadcrossorigin", StringComparison.OrdinalIgnoreCase))
361+
{
362+
header = String.Concat(header, "; crossorigin=", property.Value);
363+
}
364+
else if (property.Name.Equals("integrity", StringComparison.OrdinalIgnoreCase))
365+
{
366+
header = String.Concat(header, "; integrity=\"", property.Value, "\"");
367+
}
368+
}
369+
370+
if (header != null)
371+
{
372+
headers.Add(header);
373+
}
374+
}
375+
376+
_httpContext.Response.Headers.Link = StringValues.Concat(_httpContext.Response.Headers.Link, headers.ToArray());
377+
}
378+
}
379+
314380
private static bool IsProgressivelyEnhancedNavigation(HttpRequest request)
315381
{
316382
// For enhanced nav, the Blazor JS code controls the "accept" header precisely, so we can be very specific about the format

src/Shared/Components/ResourceCollectionResolver.cs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,17 @@ public ResourceAssetCollection ResolveResourceCollection()
4242
#if !MVC_VIEWFEATURES
4343
string? label = null;
4444
string? integrity = null;
45+
string? preloadRel = null;
46+
string? preloadAs = null;
47+
string? preloadPriority = null;
48+
string? preloadCrossorigin = null;
4549
#else
4650
string label = null;
4751
string integrity = null;
52+
string preloadRel = null;
53+
string preloadAs = null;
54+
string preloadPriority = null;
55+
string preloadCrossorigin = null;
4856
#endif
4957

5058
// If there's a selector this means that this is an alternative representation for a resource, so skip it.
@@ -59,15 +67,34 @@ public ResourceAssetCollection ResolveResourceCollection()
5967
label = property.Value;
6068
foundProperties++;
6169
}
62-
6370
else if (property.Name.Equals("integrity", StringComparison.OrdinalIgnoreCase))
6471
{
6572
integrity = property.Value;
6673
foundProperties++;
6774
}
75+
else if (property.Name.Equals("preloadrel", StringComparison.OrdinalIgnoreCase))
76+
{
77+
preloadRel = property.Value;
78+
foundProperties++;
79+
}
80+
else if (property.Name.Equals("preloadas", StringComparison.OrdinalIgnoreCase))
81+
{
82+
preloadAs = property.Value;
83+
foundProperties++;
84+
}
85+
else if (property.Name.Equals("preloadpriority", StringComparison.OrdinalIgnoreCase))
86+
{
87+
preloadPriority = property.Value;
88+
foundProperties++;
89+
}
90+
else if (property.Name.Equals("preloadcrossorigin", StringComparison.OrdinalIgnoreCase))
91+
{
92+
preloadCrossorigin = property.Value;
93+
foundProperties++;
94+
}
6895
}
6996

70-
AddResource(resources, descriptor, label, integrity, foundProperties);
97+
AddResource(resources, descriptor, label, integrity, preloadRel, preloadAs, preloadPriority, preloadCrossorigin, foundProperties);
7198
}
7299
}
73100

@@ -97,11 +124,19 @@ private static void AddResource(
97124
#if !MVC_VIEWFEATURES
98125
string? label,
99126
string? integrity,
127+
string? preloadRel,
128+
string? preloadAs,
129+
string? preloadPriority,
130+
string? preloadCrossorigin,
100131
#else
101132
string label,
102133
string integrity,
134+
string preloadRel,
135+
string preloadAs,
136+
string preloadPriority,
137+
string preloadCrossorigin,
103138
#endif
104-
int foundProperties)
139+
int foundProperties)
105140
{
106141
if (label != null || integrity != null)
107142
{
@@ -115,6 +150,22 @@ private static void AddResource(
115150
{
116151
properties[index++] = new ResourceAssetProperty("integrity", integrity);
117152
}
153+
if (preloadRel != null)
154+
{
155+
properties[index++] = new ResourceAssetProperty("preloadrel", preloadRel);
156+
}
157+
if (preloadAs != null)
158+
{
159+
properties[index++] = new ResourceAssetProperty("preloadas", preloadAs);
160+
}
161+
if (preloadPriority != null)
162+
{
163+
properties[index++] = new ResourceAssetProperty("preloadpriority", preloadPriority);
164+
}
165+
if (preloadCrossorigin != null)
166+
{
167+
properties[index++] = new ResourceAssetProperty("preloadcrossorigin", preloadCrossorigin);
168+
}
118169

119170
resources.Add(new ResourceAsset(descriptor.Route, properties));
120171
}

0 commit comments

Comments
 (0)