前言
上次,我们介绍了《如何打造单文件前后端集成 ASP.NET Core 应用》。
但是,网友说,对于 Blazor Server 项目此方法无效。
于是,我们测试了一下:
BlazorApp1.csproj
<Project Sdk="Microsoft.NET.Sdk.Web"><PropertyGroup><TargetFramework>net6.0</TargetFramework><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings><GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest></PropertyGroup><ItemGroup><PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="6.0.8" /></ItemGroup><ItemGroup><EmbeddedResource Include="wwwroot\**" /></ItemGroup>
</Project>
Program.cs
public static void Main(string[] args)
{
...app.UseFileServer(new FileServerOptions{FileProvider = new ManifestEmbeddedFileProvider(typeof(Program).Assembly, "wwwroot")});app.UseStaticFiles();
...
}
发布成单文件后运行,发现除了BlazorApp1.styles.css
,其他静态文件都可以正常加载:
BlazorApp1.styles.css 在哪里?
查找BlazorApp1.styles.css
文件,我们发现它并不在项目源码下的wwwroot
目录,而是在obj\Debug\net6.0\scopedcss\bundle
目录。
这说明,它是在编译中生成的。
查看官方文档,原来这是被称为CSS 隔离的特性。
CSS 隔离
若要定义组件特定的样式,需要创建一个同名的.razor.css
文件,例如NavMenu.razor.css
。
定义的样式仅应用于对应组件的呈现输出。在应用的其他位置定义的任何同名 CSS 声明都不会与组件的样式冲突。
CSS 隔离在生成时发生。Blazor 会重写 CSS 选择器以匹配组件呈现的标记。重写的 CSS 样式被作为静态资产捆绑和生成。
也就是说,生成时会将所有组件样式合并到{ASSEMBLY NAME}.styles.css
文件中,其中占位符 {ASSEMBLY NAME} 是项目的程序集名称。
解决思路
既然BlazorApp1.styles.css
是编译中生成的,那么只需要在编译时,将生成的 css 文件复制到wwwroot
目录下,再打包到资源文件中,不就可以实现吗?
但是,查看 MSBuild 生成日志(具体使用方法请查看我以前的文章)。我们发现,生成 CSS 隔离文件的 Target _GenerateScopedCssFiles
是在编译之后执行的,而生成资源文件的 Target _GenerateEmbeddedFilesManifest
是在编译之前就执行了。
所以打包到资源文件时,根本拿不到BlazorApp1.styles.css
文件。看来此路不通!
但是转念一想,为什么一定要拿本次生成的BlazorApp1.styles.css
文件呢?我们拿上次生成的文件不就行了!!!
实现
修改代码,指定打包的资源文件源地址:
BlazorApp1.csproj
<ItemGroup><EmbeddedResource Include="bin\Release\net6.0\publish\wwwroot\**" />
</ItemGroup>
Program.cs
app.UseFileServer(new FileServerOptions
{FileProvider = new ManifestEmbeddedFileProvider(typeof(Program).Assembly, "bin\\Release\\net6.0\\publish\\wwwroot")
});
然后点击 2 次"发布"按钮,第一次点击的目的是为了生成需要打包到资源文件的"bin\Release\net6.0\publish\wwwroot"目录。
再次运行单文件,成功!
结论
本次,我们使用了一个小 trick,将生成后的文件打包成资源文件。
如果你有更好的解决方案,欢迎留言讨论!
添加微信号【MyIO666】,邀你加入技术交流群