注意
此版本不是本文的最新版本。 有关当前版本,请参阅本文的 .NET 9 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 有关当前版本,请参阅本文的 .NET 9 版本。
本文介绍用于提供静态文件的 Blazor 应用配置。
在阅读本文之前,请参阅有关通过 Map 静态资产路由终结点约定提供静态文件的一般信息,详见 ASP.NET Core 中的映射静态文件。
预加载 Blazor 的框架静态资产
在 Blazor Web App 中,框架静态资源使用 Link
头信息 自动预加载,这允许浏览器在提取和呈现初始页面之前预加载资源。
在独立 Blazor WebAssembly 应用中,框架资产被安排在浏览器 index.html
页面处理的早期阶段进行高优先级下载和缓存。
应用
OverrideHtmlAssetPlaceholders
项目文件中的 MSBuild 属性(.csproj
) 设置为true
:<PropertyGroup> <OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders> </PropertyGroup>
<link>
元素rel="preload"
包含在<head>
wwwroot/index.html
的内容中:<link rel="preload" id="webassembly" />
服务器端应用中的 Blazor 静态资产传送
提供静态资产由路由终结点约定或下表中所述的中间件管理。
功能 | API(应用程序编程接口) | .NET 版本 | 说明 |
---|---|---|---|
映射静态资产路由终结点约定 | MapStaticAssets | .NET 9 或更高版本 | 优化静态资产到客户端的传输。 |
静态文件中间件 | UseStaticFiles | 所有 .NET 版本 | 在不优化 Map Static Assets 的情况下向客户端提供静态资产,但对于映射静态资产无法管理的一些任务非常有用。 |
在大多数情况下,映射静态资产可以替换 UseStaticFiles 。 但是,映射静态资产经过优化,用于在生成和发布时从应用中的已知位置提供资产。 如果应用服务来自其他位置(如磁盘或嵌入资源)的资产,则应使用 UseStaticFiles。
映射静态资产(MapStaticAssets)替换了在提供UseBlazorFrameworkFiles框架文件的应用中对Blazor WebAssembly的调用,并且在UseBlazorFrameworkFiles中显式调用Blazor Web App是不必要的,因为在调用AddInteractiveWebAssemblyComponents时会自动调用API。
启用交互式 WebAssembly 或交互式自动呈现模式后:
- Blazor 会创建一个终结点,以将资源集合公开为 JS 模块。
- 当 WebAssembly 组件呈现到页面中时,URL 将作为持久性组件状态发送到请求正文。
- WebAssembly 启动期间,Blazor 会检索 URL、导入模块和调用函数来检索资产集合并在内存中重新构造。 URL 特定于内容并永久缓存,因此,每个用户只需为此开销成本付费一次,直到应用更新。
- 资源集合还以人工可读的 URL (
_framework/resource-collection.js
) 公开,因此 JS 有权访问资源集合,以便实现增强的导航,或实现其他框架和第三方组件的功能。
静态文件中间件()在映射静态资产(UseStaticFilesMapStaticAssets)无法处理的以下情况下非常有用:
- 从不属于生成或发布过程的磁盘中提供文件,例如在部署期间或之后添加到应用程序文件夹中的文件。
- 将路径前缀应用于 Blazor WebAssembly 静态资产文件,详见 Blazor WebAssembly资产的前缀部分。
- 配置扩展到特定内容类型的文件映射和设置静态文件选项,详见文件映射和静态文件选项部分。
有关详细信息,请参阅 ASP.NET Core 中的静态文件。
使用映射静态资产路由终结点约定传递资产
本部分适用于服务器端 Blazor 应用。
资产通过 ComponentBase.Assets 属性传递,该属性解析给定资产的指纹 URL。 在以下示例中,Bootstrap、 Blazor 项目模板应用样式表(app.css
)和 CSS 隔离样式表 (基于应用的命名空间 BlazorSample
)链接在根组件(通常是 App
组件)Components/App.razor
中:
<link rel="stylesheet" href="@Assets["bootstrap/bootstrap.min.css"]" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<link rel="stylesheet" href="@Assets["BlazorSample.styles.css"]" />
ImportMap
组件
本部分适用于 Blazor Web App该调用 MapRazorComponents。
组件 ImportMap
(ImportMap) 表示一个导入映射元素(<script type="importmap"></script>
),用于定义模块脚本的导入映射。 导入映射组件放置在根组件(通常是<head>
组件)App
的内容中Components/App.razor
。
<ImportMap />
如果未将自定义 ImportMapDefinition 分配给导入映射组件,则会根据应用的资产生成导入映射。
注意
ImportMapDefinition 创建实例的成本很高,因此我们建议在创建其他实例时缓存它们。
以下示例演示自定义导入映射定义及其创建的导入映射。
基本导入映射:
new ImportMapDefinition(
new Dictionary<string, string>
{
{ "jquery", "https://cdn.example.com/jquery.js" },
},
null,
null);
上述代码生成以下导入映射:
{
"imports": {
"jquery": "https://cdn.example.com/jquery.js"
}
}
作用域内导入映射:
new ImportMapDefinition(
null,
new Dictionary<string, IReadOnlyDictionary<string, string>>
{
["/scoped/"] = new Dictionary<string, string>
{
{ "jquery", "https://cdn.example.com/jquery.js" },
}
},
null);
上述代码生成以下导入映射:
{
"scopes": {
"/scoped/": {
"jquery": "https://cdn.example.com/jquery.js"
}
}
}
具有完整性的导入映射:
new ImportMapDefinition(
new Dictionary<string, string>
{
{ "jquery", "https://cdn.example.com/jquery.js" },
},
null,
new Dictionary<string, string>
{
{ "https://cdn.example.com/jquery.js", "sha384-abc123" },
});
上述代码生成以下导入映射:
{
"imports": {
"jquery": "https://cdn.example.com/jquery.js"
},
"integrity": {
"https://cdn.example.com/jquery.js": "sha384-abc123"
}
}
将导入映射定义 (ImportMapDefinition) 与 ImportMapDefinition.Combine 组合在一起。
导入从 ResourceAssetCollection 创建的映射,将静态资产映射到其相应的唯一 URL:
ImportMapDefinition.FromResourceCollection(
new ResourceAssetCollection(
[
new ResourceAsset(
"jquery.fingerprint.js",
[
new ResourceAssetProperty("integrity", "sha384-abc123"),
new ResourceAssetProperty("label", "jquery.js"),
])
]));
上述代码生成以下导入映射:
{
"imports": {
"./jquery.js": "./jquery.fingerprint.js"
},
"integrity": {
"jquery.fingerprint.js": "sha384-abc123"
}
}
导入地图内容安全策略 (CSP) 冲突
本部分适用于 Blazor Web App该调用 MapRazorComponents。
该ImportMap
组件呈现为内联<script>
标记,这违反了设置或default-src
指令的严格script-src
)。
有关如何通过子资源完整性(SRI)或加密随机数解决 CSP 冲突的示例,请参阅 使用子资源完整性(SRI)或随机数解决 CSP 冲突。
在应用的请求处理管道中调用 UseStaticFiles,将静态文件中间件配置为向客户端提供静态资产。 有关详细信息,请参阅 ASP.NET Core 中的静态文件。
在 .NET 8 之前的版本中,Blazor 框架静态文件(如 Blazor 脚本)通过静态文件中间件提供。 在 .NET 8 及更高版本中,Blazor 框架静态文件通过终结点路由进行映射,而不再使用静态文件中间件。
独立 Blazor WebAssembly 应用中的指纹客户端静态资产
在构建/发布期间的独立 Blazor WebAssembly 应用中,框架将使用在构建期间计算的值替代占位符 index.html
,为客户端呈现对静态资产进行指纹处理。
指纹放置在脚本文件名中blazor.webassembly.js
,并为其他 .NET 资产生成导入映射。
独立应用wwwwoot/index.html
的Blazor WebAssembly文件中必须存在以下配置才能采用指纹:
<head>
...
<script type="importmap"></script>
...
</head>
<body>
...
<script src="_framework/blazor.webassembly#[.{fingerprint}].js"></script>
...
</body>
</html>
在项目文件(.csproj
)中,属性 <OverrideHtmlAssetPlaceholders>
设置为 true
:
<PropertyGroup>
<OverrideHtmlAssetPlaceholders>true</OverrideHtmlAssetPlaceholders>
</PropertyGroup>
解析 JavaScript 互作的导入时,浏览器将使用导入映射解析指纹文件。
任何带有指纹标记的脚本 index.html
都会被框架处理以生成指纹。 例如,名为 scripts.js
的脚本文件位于应用的 wwwroot/js
文件夹中,通过在文件扩展名之前添加 #[.{fingerprint}]
进行指纹处理(.js
):
<script src="js/scripts#[.{fingerprint}].js"></script>
客户端静态资源的标识Blazor Web App
对于使用Blazor Web App(交互式自动或交互式 WebAssembly 呈现模式)客户端呈现(CSR)的情况,通过使用、MapStaticAssets
,以及启用静态资产服务器端指纹识别的ImportMap
属性(),已启用静态资产服务器端处理。 有关详细信息,请参阅 ASP.NET Core 中的映射静态文件。
要对用于 CSR 的其他 JavaScript 模块进行指纹识别,请在应用的项目文件(<StaticWebAssetFingerprintPattern>
)中使用 .csproj
项。 在以下示例中,将为应用中所有开发人员提供 .mjs
的文件添加指纹:
<ItemGroup>
<StaticWebAssetFingerprintPattern Include="JSModule" Pattern="*.mjs"
Expression="#[.{fingerprint}]!" />
</ItemGroup>
解析 JavaScript 互作的导入时,浏览器将使用导入映射解析指纹文件。
静态文件 <link>
href
格式摘要
本部分适用于所有 .NET 版本和 Blazor 应用。
下表汇总了 .NET 版本的静态文件 <link>
href
格式。
有关放置静态文件链接的 <head>
内容的位置,请参阅 ASP.NET Core Blazor 项目结构。 还可以在单个 <HeadContent>
组件中使用 来提供静态资产链接。
有关放置静态文件链接的 <head>
内容的位置,请参阅 ASP.NET Core Blazor 项目结构。
.NET 9 或更高版本
应用类型 | 值href |
示例 |
---|---|---|
Blazor Web App | @Assets["{PATH}"] |
<link rel="stylesheet" href="@Assets["app.css"]" /> <link href="@Assets["_content/ComponentLib/styles.css"]" rel="stylesheet" /> |
Blazor Server† | @Assets["{PATH}"] |
<link href="@Assets["css/site.css"]" rel="stylesheet" /> <link href="@Assets["_content/ComponentLib/styles.css"]" rel="stylesheet" /> |
独立 Blazor WebAssembly | {PATH} |
<link rel="stylesheet" href="css/app.css" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
.NET 8.x
应用类型 | 值href |
示例 |
---|---|---|
Blazor Web App | {PATH} |
<link rel="stylesheet" href="app.css" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
Blazor Server† | {PATH} |
<link href="css/site.css" rel="stylesheet" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
独立 Blazor WebAssembly | {PATH} |
<link rel="stylesheet" href="css/app.css" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
.NET 7.x 或更早版本
应用类型 | 值href |
示例 |
---|---|---|
Blazor Server† | {PATH} |
<link href="css/site.css" rel="stylesheet" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
托管 Blazor WebAssembly‡ | {PATH} |
<link href="css/app.css" rel="stylesheet" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
Blazor WebAssembly | {PATH} |
<link href="css/app.css" rel="stylesheet" /> <link href="_content/ComponentLib/styles.css" rel="stylesheet" /> |
†.NET 8 或更高版本支持 Blazor Server,但在 .NET 7 之后不再是项目模板。
‡建议在采用 .NET 8 或更高版本时将托管 Blazor WebAssembly 应用更新为 Blazor Web App。
静态 Web 资产项目模式
本部分适用于 .Client
的 Blazor Web App 项目。
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
的 .Client
项目中所需的 Blazor Web App 设置会将 Blazor WebAssembly 静态资产行为恢复为默认值,使该项目作为托管项目的一部分运行。
Blazor WebAssembly SDK (Microsoft.NET.Sdk.BlazorWebAssembly
) 以特定方式配置静态 Web 资产,以便在“独立”模式下工作,服务器只需使用库的输出。 这不适用于 Blazor Web App,其中,应用的 WebAssembly 部分是主机的逻辑部分,必须表现得更像库。 例如,项目不公开样式捆绑包(例如 BlazorSample.Client.styles.css
),而是仅向主机提供项目捆绑包,以便主机可以将其包括在自己的样式捆绑包中。
不支持更改 Default
的值 (<StaticWebAssetProjectMode>
) 或从 .Client
项目中删除该属性。
非 Development
环境中的静态文件
本部分适用于服务器端静态文件。
在本地运行应用时,静态 Web 资产仅在 Development 环境中启用。 若要在本地开发和测试期间为 Development 以外的环境启用静态文件(例如 Staging),请在 UseStaticWebAssets 文件中的 WebApplicationBuilder 上调用 Program
。
警告
为确切环境调用 UseStaticWebAssets 以防止在生产环境中激活该功能,因为如果在生产环境中调用,该功能会从磁盘上的不同位置提供文件(而不是从项目提供)。 本部分中的示例通过调用 Staging 来检查 IsStaging 环境。
if (builder.Environment.IsStaging())
{
builder.WebHost.UseStaticWebAssets();
}
Blazor WebAssembly 资产的前缀
本部分适用于 Blazor Web App。
使用 WebAssemblyComponentsEndpointOptions.PathPrefix 终结点选项设置指示 Blazor WebAssembly 资产的前缀的路径字符串。 该路径必须对应于引用的 Blazor WebAssembly 应用程序项目。
endpoints.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode(options =>
options.PathPrefix = "{PATH PREFIX}");
在上一示例中,{PATH PREFIX}
占位符是路径前缀,必须以正斜杠 (/
) 开头。
在以下示例中,路径前缀设置为 /path-prefix
:
endpoints.MapRazorComponents<App>()
.AddInteractiveWebAssemblyRenderMode(options =>
options.PathPrefix = "/path-prefix");
静态 Web 资产基路径
本部分适用于独立的 Blazor WebAssembly 应用。
发布应用会将应用的静态资产,包括 Blazor 框架文件(_framework
文件夹资产),放置在已发布输出的根路径 (/
) 中。 项目文件 (<StaticWebAssetBasePath>
) 中指定的 .csproj
属性将基路径设置到非根路径:
<PropertyGroup>
<StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>
在前面的示例中,{PATH}
占位符是路径。
如果未设置 <StaticWebAssetBasePath>
属性,则独立应用发布在 /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/
。
在前面的示例中,{TFM}
占位符是目标框架标识符(TFM)。
如果独立 <StaticWebAssetBasePath>
应用中的 Blazor WebAssembly 属性将发布的静态资产路径设置为 app1
,则发布的输出中应用的根路径为 /app1
。
在独立 Blazor WebAssembly 应用的项目文件(.csproj
)中:
<PropertyGroup>
<StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>
在发布的输出中,独立 Blazor WebAssembly 应用的路径为 /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/
。
在前面的示例中,{TFM}
占位符是目标框架标识符(TFM)。
本部分适用于独立 Blazor WebAssembly 应用和托管的 Blazor WebAssembly 解决方案。
发布应用会将应用的静态资产,包括 Blazor 框架文件(_framework
文件夹资产),放置在已发布输出的根路径 (/
) 中。 项目文件 (<StaticWebAssetBasePath>
) 中指定的 .csproj
属性将基路径设置到非根路径:
<PropertyGroup>
<StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>
在前面的示例中,{PATH}
占位符是路径。
如果不设置 <StaticWebAssetBasePath>
属性,托管解决方案的客户端应用或独立应用将按照以下路径发布:
- 托管的 Server 解决方案的 Blazor WebAssembly 项目中:
/BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/
- 独立 Blazor WebAssembly 应用中:
/BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/
如果托管的 <StaticWebAssetBasePath>
应用或独立 Client 应用的 Blazor WebAssembly 项目中的 Blazor WebAssembly 属性将发布的静态资产路径设置为 app1
,则发布的输出中应用的根路径为 /app1
。
在 Client 应用的项目文件 (.csproj
) 或独立 Blazor WebAssembly 应用的项目文件 (.csproj
) 中:
<PropertyGroup>
<StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>
在已发布的输出中:
- 托管的 Server 解决方案的 Blazor WebAssembly 项目中客户端应用的路径:
/BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/app1/
- 独立 Blazor WebAssembly 应用的路径:
/BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/
<StaticWebAssetBasePath>
属性最常用于控制单个托管部署中多个 Blazor WebAssembly 应用的已发布静态资产的路径。 有关详细信息,请参阅多个托管的 ASP.NET Core Blazor WebAssembly 应用。 该属性在独立 Blazor WebAssembly 应用中也有效。
在前面的示例中,{TFM}
占位符是目标框架标识符(TFM)。
文件映射和静态文件选项
本部分适用于服务器端静态文件。
若要使用 FileExtensionContentTypeProvider 创建其他文件映射,或者要配置其他 StaticFileOptions,请使用以下方法之一。 在以下示例中,{EXTENSION}
占位符为文件扩展名,{CONTENT TYPE}
占位符为内容类型。 以下 API 的命名空间是 Microsoft.AspNetCore.StaticFiles。
使用 通过
Program
中的StaticFileOptions 来配置选项:var provider = new FileExtensionContentTypeProvider(); provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}"; builder.Services.Configure<StaticFileOptions>(options => { options.ContentTypeProvider = provider; }); app.UseStaticFiles();
将 StaticFileOptions 直接传递到 UseStaticFiles 文件中的
Program
:var provider = new FileExtensionContentTypeProvider(); provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}"; app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
若要使用 FileExtensionContentTypeProvider 创建其他文件映射,或者要配置其他 StaticFileOptions,请使用以下方法之一。 在以下示例中,{EXTENSION}
占位符为文件扩展名,{CONTENT TYPE}
占位符为内容类型。
使用 通过
Program
中的StaticFileOptions 来配置选项:using Microsoft.AspNetCore.StaticFiles; ... var provider = new FileExtensionContentTypeProvider(); provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}"; builder.Services.Configure<StaticFileOptions>(options => { options.ContentTypeProvider = provider; });
此方法配置用于提供 Blazor 脚本的同一文件提供程序。 确保自定义配置不会干扰提供 Blazor 脚本。 例如,不要通过使用
provider.Mappings.Remove(".js")
配置提供程序来删除 JavaScript 文件的映射。在 UseStaticFiles 文件中使用两次对
Program
的调用:- 使用 StaticFileOptions 在第一次调用中配置自定义文件提供程序。
- 第二个中间件提供 Blazor 脚本,其使用 Blazor 框架提供的默认静态文件配置。
using Microsoft.AspNetCore.StaticFiles; ... var provider = new FileExtensionContentTypeProvider(); provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}"; app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider }); app.UseStaticFiles();
可以使用
_framework/blazor.server.js
执行自定义静态文件中间件来避免在提供 MapWhen 时受到干扰:app.MapWhen(ctx => !ctx.Request.Path .StartsWithSegments("/_framework/blazor.server.js"), subApp => subApp.UseStaticFiles(new StaticFileOptions() { ... }));
从多个位置提供文件
本部分中的指南仅适用于 Blazor Web App。
若要使用 CompositeFileProvider 从多个位置服务文件:
- 将 Microsoft.Extensions.FileProviders 的命名空间添加到服务器项目的
Program
文件的顶部。 - 在调用
Program
之前在服务器项目的 UseStaticFiles 文件中:- 使用静态资产的路径创建一个 PhysicalFileProvider。
- 从 CompositeFileProvider 和 WebRootFileProvider 创建 PhysicalFileProvider。 将复合文件提供程序分配回应用的 WebRootFileProvider。
示例:
在名为 AdditionalStaticAssets
的服务器项目中创建一个新文件夹。 将图像放入文件夹中。
将以下 using
语句添加到服务器项目的 Program
文件的顶部:
using Microsoft.Extensions.FileProviders;
在调用 Program
之前在服务器项目的 UseStaticFiles 文件中,添加以下代码:
var secondaryProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "AdditionalStaticAssets"));
app.Environment.WebRootFileProvider = new CompositeFileProvider(
app.Environment.WebRootFileProvider, secondaryProvider);
在应用的 Home
组件 (Home.razor
) 标记中,使用 <img>
标记引用图像:
<img src="{IMAGE FILE NAME}" alt="{ALT TEXT}" />
在上面的示例中:
-
{IMAGE FILE NAME}
占位符是图像文件名称。 如果图像文件位于AdditionalStaticAssets
文件夹的根目录,则无需提供路径段。 -
{ALT TEXT}
占位符是图像备用文本。
运行应用。