共用方式為


ASP.NET Core Blazor 靜態檔案

注意

這不是這篇文章的最新版本。 如需目前版本,請參閱本文的 .NET 8 版本

警告

不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前版本,請參閱本文的 .NET 8 版本

本文描述提供靜態檔案的 Blazor 應用程式設定。

靜態資產中介軟體

本節適用伺服器端 Blazor 應用程式。

提供靜態資產是由下表中所述的兩個中介軟體之一所管理。

中介軟體 API .NET 版本 描述
對應靜態資產 MapStaticAssets .NET 9 或更新版本 最佳化向用戶端傳遞靜態資產。
靜態檔案 UseStaticFiles 所有 .NET 版本 向用戶端提供靜態資產,無需 MapStaticAssets 的最佳化,但對於 MapStaticAssets 無法管理的某些工作很有用。

透過在應用程式的要求處理管線中呼叫 MapStaticAssets 來設定對應靜態資產中介軟體,該管線會執行以下動作:

MapStaticAssets 會透過結合建置和發佈程序來收集應用程式中靜態資產的相關資訊以運作。 執行階段程式庫會利用此資訊來有效地向瀏覽器提供靜態資產。

在大多數情況下,MapStaticAssets 可以取代 UseStaticFiles。 不過,MapStaticAssets 已針對在建置和發佈時從應用程式中的已知位置提供資產進行了最佳化。 如果應用程式提供來自其他位置的資產 (例如磁碟或內嵌資源),則應使用 UseStaticFiles

MapStaticAssets 會提供在呼叫 UseStaticFiles 時無法使用的下列優點:

  • 應用程式中所有資產的建置時間壓縮,包括 JavaScript (JS) 和樣式表,但不包括已壓縮的影像和字型資產。 Gzip (Content-Encoding: gz) 壓縮會用於開發期間。 發佈期間會將 Gzip 和 Brotli (Content-Encoding: br) 壓縮搭配使用。
  • 在建置時間使用每個檔案內容的 SHA-256 雜湊的 Base64 編碼字串對所有資產進行指紋辨識。 這可防止重複使用舊版本的檔案,即使已快取舊檔案也一樣。 對於已經過指紋辨識的資產,會使用 immutable 指示詞進行快取,這會導致瀏覽器在變更之前絕不會再次要求資產。 對於不支援 immutable 指示詞的瀏覽器,會新增 max-age 指示詞
    • 即使資產未經過指紋辨識,也會使用檔案的指紋雜湊作為 ETag 值,為每個靜態資產產生內容型 ETags。 這可確保瀏覽器只有在檔案內容變更時 (或檔案第一次下載時) 才會下載檔案。
    • 在內部,Blazor 會將實體資產對應至其指紋,讓應用程式能夠:
      • 尋找自動產生的 Blazor 資產,例如 Blazor 的 CSS 隔離功能的 Razor 元件範圍 CSS,以及JS 匯入對應所描述的 JS 資產。
      • 在頁面的 <head> 內容中產生連結標籤,以預先載入資產。
  • Visual Studio 熱重新載入開發測試期間:
    • 完整性資訊會從資產中移除,以避免在應用程式執行時因檔案變更而發生問題。
    • 不會快取靜態資產,因此無法確保瀏覽器一律擷取目前的內容。

啟用互動式 WebAssembly 或互動式自動轉譯模式時:

  • Blazor 會建立端點以將資源集合公開為 JS 模組。
  • 將 WebAssembly 元件轉譯到頁面時,會將 URL 發出至要求主體作為保存的元件狀態。
  • 在 WebAssembly 開機期間,Blazor 會擷取 URL、匯入模組,以及呼叫函式來擷取資產集合,並在記憶體中重新建構它。 URL 專屬於內容並永遠快取,因此只有在更新應用程式之前,每位使用者才需支付一次此額外負荷成本。
  • 資源集合也會在人類可讀取的 URL (_framework/resource-collection.js) 中公開,因此 JS 可以存取資源集合以增強瀏覽,或實作其他架構和協力廠商元件的功能。

對應靜態資產中介軟體不提供縮製或其他檔案轉換的功能。 縮製通常會由自訂程式碼或協力廠商工具處理。

靜態檔案中介軟體 (UseStaticFiles) 在以下 MapStaticAssets 無法處理的情況下非常有用:

使用對應靜態檔案中介軟體取用資產

本節適用伺服器端 Blazor 應用程式。

資產會透過 ComponentBase.Assets 屬性取用,其會解析指定資產經過指紋辨識的 URL。 在下列範例中,Bootstrap、Blazor 專案範本應用程式樣式表 (app.css) 和 CSS 隔離樣式表會連結在根元件中,通常是 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["BlazorWeb-CSharp.styles.css"]" />

匯入對應

本節適用伺服器端 Blazor 應用程式。

ImportMap 元件代表匯入對應元素 (<script type="importmap"></script>),這會定義模組指令碼的匯入對應。 ImportMap 元件會位於根元件的 <head> 內容中,通常是 App 元件 (Components/App.razor)。

<ImportMap />

如果未將自訂 ImportMapDefinition 指派給 ImportMap 元件,則會根據應用程式的資產產生匯入對應。

下列範例會示範自訂匯入對應定義和其建立的匯入對應。

基本匯入對應:

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"
  }
}

透過在應用程式的要求處理管線中呼叫 UseStaticFiles,設定靜態檔案中介軟體以提供靜態資產給用戶端。 如需詳細資訊,請參閱 ASP.NET Core 中的靜態檔案

在 .NET 8 之前的版本中,會透過靜態檔案中介軟體提供 Blazor 指令碼這類 Blazor 架構靜態檔案。 在 .NET 8 或更新版本中,會使用端點路由來對應 Blazor 架構靜態檔案,而且不再使用靜態檔案中介軟體。

本章節適用於所有 .NET 版本和 Blazor 應用程式。

下表會摘要說明 .NET 版本的靜態檔案 <link> href 格式。

如需放置靜態檔案連結的 <head> 內容的位置,請參閱 ASP.NET Core Blazor 專案結構。 靜態資產連結也可以使用個別 Razor 元件中的 <HeadContent> 元件來提供。

如需放置靜態檔案連結的 <head> 內容的位置,請參閱 ASP.NET Core Blazor 專案結構

.NET 9 或更新版本

應用程式類型 href 範例
Blazor Web 應用程式 @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 應用程式 {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 Apps。

靜態 Web 資產專案模式

本節適用於 Blazor Web 應用程式的 .Client 專案。

Blazor Web 應用程式的 .Client 專案中的必要 <StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode> 設定會將 Blazor WebAssembly 靜態資產行為還原回預設值,讓專案作為託管專案的一部分運作。 Blazor WebAssembly SDK (Microsoft.NET.Sdk.BlazorWebAssembly) 會以特定方式設定靜態 Web 資產,以「獨立」模式運作,而伺服器只需取用程式庫的輸出即可。 這不適用於 Blazor Web 應用程式,其中應用程式的 WebAssembly 部分是主機的邏輯部分,而且必須表現出更像程式庫的行為。 例如,專案不會公開樣式組合 (例如 BlazorSample.Client.styles.css),而是只向主機提供專案組合,讓主機可以將該組合包含在自己的樣式組合中。

支援變更 <StaticWebAssetProjectMode> 的值 (Default) 或從 .Client 專案移除屬性。

Development 環境中的靜態檔案

本節適用於伺服器端靜態檔案。

在本機執行應用程式時,靜態 Web 資產預設只會在 Development 環境中啟用。 若要在本機開發和測試期間為 Development 以外的環境啟用靜態檔案 (例如,Staging),請在 Program 檔案中的 WebApplicationBuilder 上呼叫 UseStaticWebAssets

警告

呼叫 UseStaticWebAssets 以取得防止在生產環境中啟用功能的確切環境,因為在生產環境中呼叫時,它會從磁碟上專案以外的不同位置提供檔案。 本節中的範例會呼叫 IsStaging 來檢查 Staging 環境。

if (builder.Environment.IsStaging())
{
    builder.WebHost.UseStaticWebAssets();
}

Blazor WebAssembly 資產的前置詞

本節適用於 Blazor Web Apps。

使用 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 資料夾資產),放在已發佈輸出中的根路徑 (/)。 專案檔 (.csproj) 中指定的 <StaticWebAssetBasePath> 屬性會將基礎路徑設定為非根路徑:

<PropertyGroup>
  <StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>

在上述範例中,{PATH} 預留位置是路徑。

若未設定 <StaticWebAssetBasePath> 屬性,獨立應用程式會在 /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/ 發佈。

在上述範例中,{TFM} 預留位置是目標 Framework Moniker (TFM) (例如,net6.0)。

如果獨立 Blazor WebAssembly 應用程式中的 <StaticWebAssetBasePath> 屬性將已發佈的靜態資產路徑設定為 app1,則已發佈輸出中應用程式的根路徑為 /app1

在獨立 Blazor WebAssembly 應用程式的專案檔中 (.csproj):

<PropertyGroup>
  <StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>

在發佈的輸出中,獨立 Blazor WebAssembly 應用程式的路徑為 /BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/app1/

在上述範例中,{TFM} 預留位置是目標 Framework Moniker (TFM) (例如,net6.0)。

本節適用獨立 Blazor WebAssembly 應用程式和裝載的 Blazor WebAssembly 方案。

依預設,發佈應用程式會將應用程式的靜態資產,包括 Blazor 架構檔案 (_framework 資料夾資產),放在已發佈輸出中的根路徑 (/)。 專案檔 (.csproj) 中指定的 <StaticWebAssetBasePath> 屬性會將基礎路徑設定為非根路徑:

<PropertyGroup>
  <StaticWebAssetBasePath>{PATH}</StaticWebAssetBasePath>
</PropertyGroup>

在上述範例中,{PATH} 預留位置是路徑。

若未設定 <StaticWebAssetBasePath> 屬性,裝載的方案或獨立應用程式的用戶端應用程式會在下列路徑發佈:

  • 裝載的 Blazor WebAssembly 方案的 Server 專案:/BlazorHostedSample/Server/bin/Release/{TFM}/publish/wwwroot/
  • 在獨立 Blazor WebAssembly 應用程式中:/BlazorStandaloneSample/bin/Release/{TFM}/publish/wwwroot/

如果裝載的 Blazor WebAssembly 應用程式或獨立 Blazor WebAssembly 應用程式中 Client 專案的 <StaticWebAssetBasePath> 屬性將已發佈的靜態資產路徑設定為 app1,則已發佈輸出中應用程式的根路徑為 /app1

Client 應用程式的專案檔 (.csproj) 或獨立 Blazor WebAssembly 應用程式的專案檔中 (.csproj):

<PropertyGroup>
  <StaticWebAssetBasePath>app1</StaticWebAssetBasePath>
</PropertyGroup>

在發佈的輸出中:

  • 裝載的 Blazor WebAssembly 方案的 Server 專案中用戶端應用程式的路徑:/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} 預留位置是目標 Framework Moniker (TFM) (例如,net6.0)。

檔案對應和靜態檔案選項

本節適用於伺服器端靜態檔案。

若要使用 FileExtensionContentTypeProvider 或設定其他 StaticFileOptions 來建立其他檔案對應,請使用下列其中一種方法。 在下列範例中,{EXTENSION} 預留位置是副檔名,而 {CONTENT TYPE} 預留位置是內容類型。 下列 API 的命名空間為 Microsoft.AspNetCore.StaticFiles

  • 使用 StaticFileOptionsProgram 檔案中透過相依性插入 (DI) 設定選項:

    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    builder.Services.Configure<StaticFileOptions>(options =>
    {
        options.ContentTypeProvider = provider;
    });
    
    app.UseStaticFiles();
    
  • StaticFileOptions 直接傳遞至 Program 檔案中的 UseStaticFiles

    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings["{EXTENSION}"] = "{CONTENT TYPE}";
    
    app.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = provider });
    

若要使用 FileExtensionContentTypeProvider 或設定其他 StaticFileOptions 來建立其他檔案對應,請使用下列其中一種方法。 在下列範例中,{EXTENSION} 預留位置是副檔名,而 {CONTENT TYPE} 預留位置是內容類型。

  • 使用 StaticFileOptionsProgram 檔案中透過相依性插入 (DI) 設定選項:

    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 檔案的對應。

  • Program 檔案中使用對 UseStaticFiles 的兩個呼叫:

    • 使用 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 Apps。

若要使用 CompositeFileProvider 提供來自多個位置的檔案:

範例:

在名為 AdditionalStaticAssets 的伺服器專案中建立新資料夾。 將影像放入資料夾中。

將下列 using 陳述式新增至伺服器專案的 Program 檔案頂端:

using Microsoft.Extensions.FileProviders;

在呼叫 UseStaticFiles 之前的伺服器專案 Program 檔案中,新增下列程式碼:

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} 預留位置是影像替代文字。

執行應用程式。

其他資源