PAYATHON 2026

如何自定义 Blazor Web App 中 scoped CSS bundle 的路由路径?

技术老齐

结论

只需通过自定义 URL 访问 <ProjectName>.styles.css 时,可以在路由匹配前重写请求路径,无需编写 MSBuild target 或修改 *.staticwebassets.endpoints.json。

要统一调整静态资源的基础路径,可以使用项目属性 StaticWebAssetBasePath。它也会影响其他静态资源,不适合只修改一个 CSS bundle。

以下示例适用于使用 MapStaticAssets() 的 Blazor Web App。该 API 适用于 .NET 9 及更高版本。Blazor 静态文件文档

为什么不必修改构建清单

CSS isolation 会在构建时重写选择器并生成 bundle。对外访问的 URL 可以通过服务器端重写规则调整:MapStaticAssets() 按原有路径提供资源,浏览器仍使用自定义 URL。CSS isolation 文档、URL 重写文档

例如:

浏览器请求:/custom/path/styles.css
内部路径:  /MyApp.styles.css

这样会增加一个访问入口,原有的 /MyApp.styles.css 地址仍然可用,生成文件的名称和构建清单也保持原样。

方案一:为 bundle 添加自定义访问路径

假设应用生成的 bundle 名称为 MyApp.styles.css,希望通过 /custom/path/styles.css 访问。

在 Program.cs 中加入重写规则:

using Microsoft.AspNetCore.Rewrite;

// 保留项目原有的服务注册和 builder.Build()。

app.UseHttpsRedirection();

var rewriteOptions = new RewriteOptions()
    .AddRewrite(
        @"^custom/path/styles\.css$",
        "MyApp.styles.css",
        skipRemainingRules: true);

app.UseRewriter(rewriteOptions);

// 显式安排路由匹配,确保重写先执行。
app.UseRouting();

// 将项目原有的认证、授权和防伪中间件
// 按原有依赖关系安排在这里。

app.MapStaticAssets();

// 保留项目原有的 MapRazorComponents 等端点映射。

AddRewrite 的匹配表达式不包含开头的 /。这是服务器内部重写,不会向浏览器返回跳转响应。URL 重写配置说明

MapStaticAssets() 负责注册端点,路由中间件负责匹配端点。因此,仅将 UseRewriter() 写在 MapStaticAssets() 前面还不够;显式调用 UseRouting(),才能保证路由匹配在路径重写之后执行。ASP.NET Core 路由顺序说明

然后,将 Components/App.razor 中对应的样式引用改为:

<link rel="stylesheet" href="custom/path/styles.css" />

这个地址相对于 <base href>。如果应用部署在子路径下,还需要正确配置应用基础路径,让重写规则处理去除 PathBase 后的请求路径。

子目录路径需要检查 CSS 的相对引用

样式表改为通过 /custom/path/ 下的地址访问后,浏览器会基于新地址解析其中的相对 @import 和 url(...)。

例如,bundle 中包含:

@import '_content/MyLibrary/MyLibrary.bundle.scp.css';

浏览器就会请求:

/custom/path/_content/MyLibrary/MyLibrary.bundle.scp.css

可以在同一组规则中补充:

rewriteOptions.AddRewrite(
    @"^custom/path/_content/(.*)$",
    "_content/$1",
    skipRemainingRules: true);

这条规则也要在 app.UseRewriter(rewriteOptions) 之前配置。图片、字体等其他相对路径,需要根据实际请求处理。如果只想更换文件名,使用应用根目录下的 /styles.css,可以避免目录变化带来的这类问题。

方案二:统一调整静态资源基础路径

要给静态资源统一添加前缀,可以在 .csproj 中配置:

<PropertyGroup>
  <StaticWebAssetBasePath>assets</StaticWebAssetBasePath>
</PropertyGroup>

StaticWebAssetBasePath 是文档列出的构建配置项,会影响 scoped CSS bundle 和其他应用静态资源。它不能用于单独重命名某个 bundle,也不等同于修改整个应用的基础路径。CSS isolation 基础路径配置

没有自定义 URL 要求时,通常可以直接使用:

<link rel="stylesheet" href="@Assets["MyApp.styles.css"]" />

Assets 用于解析资源对应的 URL,包括适用的指纹路径,但不会创建新的自定义路由。静态资源引用说明

是否需要编写 MSBuild target

仅增加自定义访问 URL 时,无需编写 MSBuild target。如果要求生成的资源清单也记录新路径,就需要针对具体 SDK 版本修改构建管线。

SDK 会分别生成构建和发布清单,并处理资源路径、指纹及相关端点。因此,只用 AfterTargets="Build" 替换 JSON 中的字符串,并不能完成这项配置。静态资源构建 targets

题目没有提供 SDK 版本,无法给出可靠、通用的清单修改 target。选择这种做法时,需要固定 SDK 版本,同时检查构建、发布和资源引用的结果。

如果已有自己的前端构建工具,需要完全接管 bundle 的名称和输出位置,可以关闭自动 bundling:

<PropertyGroup>
  <DisableScopedCssBundling>true</DisableScopedCssBundling>
</PropertyGroup>

关闭后,需要由自己的流程收集 obj 中的隔离 CSS、合并文件、发布资源并维护加载路径。该属性不会自动生成一个可任意命名的新 bundle。关闭自动 bundling 的说明

配置完成后,应分别在开发运行和发布部署环境中检查自定义 URL,确认返回的是 CSS,依赖资源也没有出现 404。固定别名不会随内容更新而自动改变 URL,需要据此配置缓存策略,不能直接套用指纹资源的永久缓存方式。

备注:内容仅供参考。