如何打造单文件 Blazor Server 应用

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何打造单文件 Blazor Server 应用相关的知识,希望对你有一定的参考价值。

前言

上次,我们介绍了《如何打造单文件前后端集成 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】,邀你加入技术交流群

以上是关于如何打造单文件 Blazor Server 应用的主要内容,如果未能解决你的问题,请参考以下文章

如何将 returnUrl 传递到 Blazor Server 应用程序中的登录页面?

Blazor Server 如何跨多个选项卡和刷新保存数据

当我只告诉它调用一个函数时,Blazor Server 应用程序中的 JSRuntime.InvokeVoidAsync 调用多个函数

在哪里可以找到有关如何将 Blazor 应用部署到在 Windows Server 2019 上运行的 IIS10 的具体详细信息

如何制作 Blazor 页面互斥锁

通过Blazor使用C#开发SPA单页面应用程序 - Ant Design Button