Skip to content

Commit 3f0e24b

Browse files
committed
[Blazor] Move Blazor to use Static Web Assets
* Plugs-in Blazor wasm through the static web assets infrastructure. * Avoids the need for a custom Blazor.config file. * Removes broken auto-rebuild and debug support. * Removes unnecessary server-side Blazor helpers.
1 parent 4ab5fe6 commit 3f0e24b

23 files changed

+156
-751
lines changed

src/Components/Blazor/Build/src/targets/All.props

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
<Project>
22
<Import Project="Blazor.MonoRuntime.props" />
33

4+
<Import Project="StaticWebAssets.props" />
5+
46
<PropertyGroup>
5-
<DefaultWebContentItemExcludes>$(DefaultWebContentItemExcludes);wwwroot\**</DefaultWebContentItemExcludes>
7+
8+
<!-- Assets for a Blazor app are exposed on the root folder by default. -->
9+
<StaticWebAssetBasePath>/</StaticWebAssetBasePath>
610

711
<!-- When using IISExpress with a standalone app, there's no point restarting IISExpress after build. It slows things unnecessarily and breaks in-flight HTTP requests. -->
812
<NoRestartServerOnBuild>true</NoRestartServerOnBuild>

src/Components/Blazor/Build/src/targets/All.targets

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,4 @@
2222
<Import Project="Publish.targets" />
2323
<Import Project="StaticWebAssets.targets" />
2424

25-
<Target Name="GenerateBlazorMetadataFile"
26-
BeforeTargets="GetCopyToOutputDirectoryItems">
27-
<PropertyGroup>
28-
<BlazorMetadataFileName>$(AssemblyName).blazor.config</BlazorMetadataFileName>
29-
<BlazorMetadataFilePath>$(TargetDir)$(BlazorMetadataFileName)</BlazorMetadataFilePath>
30-
</PropertyGroup>
31-
32-
<ItemGroup>
33-
<_BlazorConfigContent Include="$(MSBuildProjectFullPath)" />
34-
<_BlazorConfigContent Include="$(TargetPath)" />
35-
<_BlazorConfigContent Include="debug:true" Condition="'$(BlazorEnableDebugging)'=='true'" />
36-
</ItemGroup>
37-
38-
<WriteLinesToFile
39-
File="$(BlazorMetadataFilePath)"
40-
Lines="@(_BlazorConfigContent)"
41-
Overwrite="true"
42-
WriteOnlyWhenDifferent="True" />
43-
44-
<ItemGroup>
45-
<ContentWithTargetPath Include="$(BlazorMetadataFilePath)" TargetPath="$(BlazorMetadataFileName)" CopyToOutputDirectory="PreserveNewest" />
46-
</ItemGroup>
47-
</Target>
48-
4925
</Project>

src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,6 @@
6666
</BlazorOutputWithTargetPath>
6767
</ItemGroup>
6868

69-
<ItemGroup Label="Static content supplied by NuGet packages">
70-
<_BlazorPackageContentOutput Include="@(BlazorPackageContentFile)" Condition="%(SourcePackage) != ''">
71-
<TargetOutputPath>$(BaseBlazorPackageContentOutputPath)%(SourcePackage)\%(RecursiveDir)\%(Filename)%(Extension)</TargetOutputPath>
72-
</_BlazorPackageContentOutput>
73-
<BlazorOutputWithTargetPath Include="@(_BlazorPackageContentOutput)" />
74-
</ItemGroup>
7569
</Target>
7670

7771
<Target Name="_ResolveBlazorInputs" DependsOnTargets="ResolveReferences;ResolveRuntimePackAssets">

src/Components/Blazor/Build/src/targets/Publish.targets

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,59 +12,28 @@
1212
<IsWebConfigTransformDisabled>true</IsWebConfigTransformDisabled>
1313
</PropertyGroup>
1414

15-
<Target Name="BlazorGetCopyToPublishDirectoryItems"
15+
<Target Name="_BlazorRemoveResolvedAssembliesFromPublish"
1616
BeforeTargets="GetCopyToPublishDirectoryItems"
1717
DependsOnTargets="PrepareBlazorOutputs"
1818
Condition="'$(OutputType.ToLowerInvariant())'=='exe'">
19+
1920
<ItemGroup>
2021
<!-- Don't want to publish the assemblies from the regular 'bin' dir. Instead we publish ones from 'dist'. -->
2122
<ResolvedAssembliesToPublish Remove="@(ResolvedAssembliesToPublish)" />
22-
23-
<!-- Move wwwroot files to output root -->
24-
<ContentWithTargetPath Update="@(ContentWithTargetPath)" Condition="$([System.String]::new(%(TargetPath)).StartsWith('wwwroot\')) OR $([System.String]::new(%(TargetPath)).StartsWith('wwwroot/'))">
25-
<TargetPath>$(BlazorPublishDistDir)$([System.String]::new(%(TargetPath)).Substring(8))</TargetPath>
26-
</ContentWithTargetPath>
27-
28-
<!-- Publish all the 'dist' files -->
29-
<_BlazorGCTPDI Include="%(BlazorOutputWithTargetPath.Identity)">
30-
<TargetPath>$(AssemblyName)\%(TargetOutputPath)</TargetPath>
31-
</_BlazorGCTPDI>
32-
33-
<ContentWithTargetPath Include="@(_BlazorGCTPDI)">
34-
<TargetPath>%(TargetPath)</TargetPath>
35-
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
36-
</ContentWithTargetPath>
3723
</ItemGroup>
38-
39-
<!-- Replace the .blazor.config contents with what we need to serve in production -->
40-
<PropertyGroup>
41-
<_BlazorConfigPath>$(OutDir)$(AssemblyName).blazor.config</_BlazorConfigPath>
42-
</PropertyGroup>
43-
44-
<ItemGroup>
45-
<_BlazorPublishConfigContent Include="." />
46-
<_BlazorPublishConfigContent Include="$(AssemblyName)/" />
47-
</ItemGroup>
48-
49-
<WriteLinesToFile
50-
File="$(_BlazorConfigPath)"
51-
Lines="@(_BlazorPublishConfigContent)"
52-
Overwrite="true"
53-
WriteOnlyWhenDifferent="true" />
5424
</Target>
5525

5626
<!-- The following target runs only for standalone publishing -->
5727
<Target Name="BlazorCompleteStandalonePublish" AfterTargets="CopyFilesToPublishDirectory">
5828
<!-- Add a suitable web.config file if there isn't one already -->
29+
5930
<ItemGroup>
6031
<_StandaloneWebConfigContent Include="$([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)Standalone.Web.config'))"/>
6132
</ItemGroup>
33+
6234
<WriteLinesToFile
6335
Condition="!Exists('$(PublishDir)web.config')"
6436
File="$(PublishDir)web.config"
6537
Lines="@(_StandaloneWebConfigContent->Replace('[ServeSubdirectory]','$(BlazorPublishDistDir)'))" />
66-
67-
<!-- Remove the .blazor.config file, since it's irrelevant for standalone publishing -->
68-
<Delete Files="$(PublishDir)$(AssemblyName).blazor.config" />
6938
</Target>
7039
</Project>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project>
2+
<PropertyGroup>
3+
<ResolveCurrentProjectStaticWebAssetsInputsDependsOn>
4+
_ResolveBlazorGeneratedAssets;
5+
$(ResolveCurrentProjectStaticWebAssetsInputsDependsOn)
6+
</ResolveCurrentProjectStaticWebAssetsInputsDependsOn>
7+
</PropertyGroup>
8+
</Project>
Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,65 @@
11
<Project>
22

33
<PropertyGroup>
4-
<ResolveStaticWebAssetsInputsDependsOn>
5-
$(ResolveStaticWebAssetsInputsDependsOn);
6-
_RemoveBlazorCurrentProjectAssetsFromStaticWebAssets;
7-
</ResolveStaticWebAssetsInputsDependsOn>
8-
9-
<GetCurrentProjectStaticWebAssetsDependsOn>
10-
$(GetCurrentProjectStaticWebAssetsDependsOn);
11-
_RemoveBlazorCurrentProjectAssetsFromStaticWebAssets;
12-
</GetCurrentProjectStaticWebAssetsDependsOn>
4+
<ResolveCurrentProjectStaticWebAssetsDependsOn>
5+
_ResolveBlazorGeneratedAssets;
6+
$(ResolveCurrentProjectStaticWebAssetsDependsOn);
7+
</ResolveCurrentProjectStaticWebAssetsDependsOn>
138
</PropertyGroup>
149

15-
16-
<Target Name="_RemoveBlazorCurrentProjectAssetsFromStaticWebAssets">
10+
<Target Name="_ResolveBlazorGeneratedAssets" DependsOnTargets="PrepareBlazorOutputs">
1711
<ItemGroup>
18-
<StaticWebAsset Remove="@(StaticWebAsset)" Condition="'%(SourceType)' == ''" />
12+
<StaticWebAsset Include="@(BlazorOutputWithTargetPath->'$(TargetDir)%(TargetOutputPath)')" RemoveMetadata="TargetOutputPath">
13+
<SourceType></SourceType>
14+
<SourceId>$(PackageId)</SourceId>
15+
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)\dist\'))</ContentRoot>
16+
<BasePath>$(StaticWebAssetBasePath)</BasePath>
17+
<RelativePath>$([System.String]::Copy('%(TargetOutputPath)').Replace('dist\','').Replace('\','/'))</RelativePath>
18+
</StaticWebAsset>
19+
20+
<!-- We are dependingo on a "private" property for static web assets, but this is something we can clean-up in a later release.
21+
These files are not "external" in the "traditional" sense but it is fine for now as this is an implementation detail. -->
22+
<_ExternalStaticWebAsset Include="@(BlazorOutputWithTargetPath->'$(TargetDir)%(TargetOutputPath)')">
23+
<SourceId>$(PackageId)</SourceId>
24+
<!-- We just do this to keep the existing implementation happy. We will update this in the next release. -->
25+
<SourceType>Generated</SourceType>
26+
<ContentRoot>$([MSBuild]::NormalizeDirectory('$(TargetDir)\dist\'))</ContentRoot>
27+
<BasePath>$(StaticWebAssetBasePath)</BasePath>
28+
</_ExternalStaticWebAsset>
1929
</ItemGroup>
30+
2031
</Target>
2132

2233
<Target Name="BlazorStaticWebAssetsComputeFilesToPublish"
2334
AfterTargets="_StaticWebAssetsComputeFilesToPublish">
2435

2536
<ItemGroup>
2637
<!-- We need to update the external static web assets to follow the blazor publish output convention that puts them inside $(TargetName)/dist instead of wwwroot -->
27-
<_StandaloneExternalPublishStaticWebAsset Include="@(_ExternalPublishStaticWebAsset)" Condition="'%(RelativePath)' != ''">
38+
<_StandaloneExternalPublishStaticWebAsset Include="@(_ExternalPublishStaticWebAsset)" Condition="'%(RelativePath)' != '' and '$([System.String]::Copy(%(Identity))).StartsWith($(MSBuildThisProjectDirectory))' != 'true'">
2839
<RelativePath>$([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)', '$([MSBuild]::NormalizePath('$([System.Text.RegularExpressions.Regex]::Replace('%(RelativePath)','^wwwroot\\?\/?(.*)','$(BlazorPublishDistDir)$1'))'))'))</RelativePath>
2940
</_StandaloneExternalPublishStaticWebAsset>
3041

42+
<_CurrentProjectWwwrootStaticWebAsset Include="@(StaticWebAsset)" Exclude="@(BlazorOutputWithTargetPath->'$(TargetDir)%(TargetOutputPath)')" Condition="'%(StaticWebAsset.SourceType)' == ''" />
43+
44+
<_StandaloneWwwrootCurrentProjectPublishStaticWebAsset Include="%(_CurrentProjectWwwrootStaticWebAsset.Identity)">
45+
<RelativePath>$(BlazorPublishDistDir)%(RelativePath)</RelativePath>
46+
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
47+
</_StandaloneWwwrootCurrentProjectPublishStaticWebAsset>
48+
3149
<!-- Update doesn't work inside targets so we need to remove the items and re-add them. See https://github.com/microsoft/msbuild/issues/2835 for details -->
32-
<ResolvedFileToPublish Remove="@(_StandaloneExternalPublishStaticWebAsset)" />
50+
<ResolvedFileToPublish Remove="@(_ExternalPublishStaticWebAsset)" />
3351
<ResolvedFileToPublish Include="@(_StandaloneExternalPublishStaticWebAsset)" />
3452

53+
<!-- Gets rid of the content and sets it up on the right path -->
54+
<ResolvedFileToPublish Remove="@(_CurrentProjectWwwrootStaticWebAsset)" />
55+
<ResolvedFileToPublish Include="@(_StandaloneWwwrootCurrentProjectPublishStaticWebAsset)" />
56+
57+
<!-- Makes sure the generated static web assets for this project are copied to the expected output folder -->
58+
<ResolvedFileToPublish Include="@(StaticWebAsset)" Exclude="@(_CurrentProjectWwwrootStaticWebAsset)" Condition="'@(SourceType)' == ''">
59+
<RelativePath>$(BlazorPublishDistDir)%(RelativePath)</RelativePath>
60+
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
61+
</ResolvedFileToPublish>
62+
3563
</ItemGroup>
3664
</Target>
3765
</Project>

src/Components/Blazor/Build/test/BuildIntegrationTests/BuildIntegrationTest.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,8 @@ public async Task Build_Hosted_Works()
3939
Assert.BuildPassed(result);
4040

4141
var buildOutputDirectory = project.BuildOutputDirectory;
42-
var blazorConfig = Path.Combine(buildOutputDirectory, "standalone.blazor.config");
43-
Assert.FileExists(result, blazorConfig);
4442

4543
var path = Path.GetFullPath(Path.Combine(project.SolutionPath, "standalone", "bin", project.Configuration, "netstandard2.1", "standalone.dll"));
46-
Assert.FileContains(result, blazorConfig, path);
4744
Assert.FileDoesNotExist(result, buildOutputDirectory, "dist", "_framework", "_bin", "standalone.dll");
4845
}
4946

src/Components/Blazor/Build/test/BuildIntegrationTests/PublishIntegrationTest.cs

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -155,31 +155,23 @@ public async Task Publish_HostedApp_Works()
155155
// Make sure the main project exists
156156
Assert.FileExists(result, publishDirectory, "blazorhosted.dll");
157157

158-
var blazorPublishDirectory = Path.Combine(publishDirectory, "standalone");
159-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json");
160-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js");
161-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm");
162-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js");
163-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll");
164-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
158+
var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");
159+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.boot.json");
160+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.webassembly.js");
161+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", "mono.wasm");
162+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", "mono.js");
163+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "standalone.dll");
164+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
165165

166166
// Verify static assets are in the publish directory
167-
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
167+
Assert.FileExists(result, blazorPublishDirectory, "index.html");
168168

169169
// Verify static web assets from referenced projects are copied.
170170
Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
171171
Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css");
172172

173-
// Verify static assets are in the publish directory
174-
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
175-
176173
// Verify web.config
177174
Assert.FileExists(result, publishDirectory, "web.config");
178-
179-
var blazorConfig = Path.Combine(result.Project.DirectoryPath, publishDirectory, "standalone.blazor.config");
180-
var blazorConfigLines = File.ReadAllLines(blazorConfig);
181-
Assert.Equal(".", blazorConfigLines[0]);
182-
Assert.Equal("standalone/", blazorConfigLines[1]);
183175
}
184176

185177
[Fact]
@@ -198,24 +190,21 @@ public async Task Publish_HostedApp_WithNoBuild_Works()
198190
// Make sure the main project exists
199191
Assert.FileExists(result, publishDirectory, "blazorhosted.dll");
200192

201-
var blazorPublishDirectory = Path.Combine(publishDirectory, "standalone");
202-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.boot.json");
203-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "blazor.webassembly.js");
204-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.wasm");
205-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "wasm", "mono.js");
206-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "standalone.dll");
207-
Assert.FileExists(result, blazorPublishDirectory, "dist", "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
193+
var blazorPublishDirectory = Path.Combine(publishDirectory, "wwwroot");
194+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.boot.json");
195+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "blazor.webassembly.js");
196+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", "mono.wasm");
197+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "wasm", "mono.js");
198+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "standalone.dll");
199+
Assert.FileExists(result, blazorPublishDirectory, "_framework", "_bin", "Microsoft.Extensions.Logging.Abstractions.dll"); // Verify dependencies are part of the output.
208200

209201
// Verify static assets are in the publish directory
210-
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
202+
Assert.FileExists(result, blazorPublishDirectory, "index.html");
211203

212204
// Verify static web assets from referenced projects are copied.
213205
// Uncomment once https://github.com/aspnet/AspNetCore/issues/17426 is resolved.
214-
// Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
215-
// Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css");
216-
217-
// Verify static assets are in the publish directory
218-
Assert.FileExists(result, blazorPublishDirectory, "dist", "index.html");
206+
Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "wwwroot", "exampleJsInterop.js");
207+
Assert.FileExists(result, publishDirectory, "wwwroot", "_content", "RazorClassLibrary", "styles.css");
219208

220209
// Verify web.config
221210
Assert.FileExists(result, publishDirectory, "web.config");

src/Components/Blazor/DevServer/src/Server/Startup.cs

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public void ConfigureServices(IServiceCollection services)
2828
{
2929
services.AddRouting();
3030

31+
services.AddBlazorStaticFilesConfiguration();
32+
3133
services.AddResponseCompression(options =>
3234
{
3335
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[]
@@ -40,43 +42,22 @@ public void ConfigureServices(IServiceCollection services)
4042

4143
public void Configure(IApplicationBuilder app, IWebHostEnvironment environment, IConfiguration configuration)
4244
{
43-
var applicationAssemblyFullPath = ResolveApplicationAssemblyFullPath();
44-
4545
app.UseDeveloperExceptionPage();
4646
app.UseResponseCompression();
4747
EnableConfiguredPathbase(app, configuration);
4848

4949
app.UseBlazorDebugging();
5050

5151
app.UseStaticFiles();
52-
app.UseClientSideBlazorFiles(applicationAssemblyFullPath);
5352

5453
app.UseRouting();
5554

5655
app.UseEndpoints(endpoints =>
5756
{
58-
endpoints.MapFallbackToClientSideBlazor(applicationAssemblyFullPath, "index.html");
57+
endpoints.MapFallbackToFile("index.html");
5958
});
6059
}
6160

62-
private string ResolveApplicationAssemblyFullPath()
63-
{
64-
const string applicationPathKey = "applicationpath";
65-
var configuredApplicationPath = Configuration.GetValue<string>(applicationPathKey);
66-
if (string.IsNullOrEmpty(configuredApplicationPath))
67-
{
68-
throw new InvalidOperationException($"No value was supplied for the required option '{applicationPathKey}'.");
69-
}
70-
71-
var resolvedApplicationPath = Path.GetFullPath(configuredApplicationPath);
72-
if (!File.Exists(resolvedApplicationPath))
73-
{
74-
throw new InvalidOperationException($"Application assembly not found at {resolvedApplicationPath}.");
75-
}
76-
77-
return resolvedApplicationPath;
78-
}
79-
8061
private static void EnableConfiguredPathbase(IApplicationBuilder app, IConfiguration configuration)
8162
{
8263
var pathBase = configuration.GetValue<string>("pathbase");

0 commit comments

Comments
 (0)