裝載及部署 ASP.NET Core Blazor WebAssembly

注意

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

重要

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

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

本文說明如何使用 ASP.NET Core、內容傳遞網路 (CDN)、檔案伺服器和 GitHub Pages 來裝載和部署 Blazor WebAssembly。

警告

本文參考 CentOS,這是即將結束生命週期 (EOL) 狀態的 Linux 發行版本。 請據以考慮您的使用和規劃。 如需詳細資訊,請參閱本文的 CentOS 一節。

使用 Blazor WebAssembly 裝載模型時:

  • Blazor 應用程式、其相依性以及 .NET 執行階段會平行下載至瀏覽器中。
  • 應用程式會直接在瀏覽器 UI 執行緒上執行。

本文與 Blazor 應用程式放在靜態裝載的網頁伺服器或服務上,且未使用 .NET 來提供 Blazor 應用程式的部署案例有關。 此策略的說明請見獨立部署一節,該節包含以 IIS 子應用程式的形式來裝載 Blazor WebAssembly 應用程式的相關資訊。

支援的部署策略如下:

  • Blazor 應用程式由 ASP.NET Core 應用程式提供。 此策略已於搭配 ASP.NET Core 的已裝載部署一節中涵蓋。
  • Blazor 應用程式放在靜態裝載的網頁伺服器或服務上,且未使用 .NET 來提供 Blazor 應用程式。 此策略的說明請見獨立部署一節,該節包含以 IIS 子應用程式的形式來裝載 Blazor WebAssembly 應用程式的相關資訊。
  • ASP.NET Core 應用程式裝載多個 Blazor WebAssembly 應用程式。 如需詳細資訊,請參閱多個裝載的 ASP.NET Core Blazor WebAssembly 應用程式

減少某些行動裝置瀏覽器的最大堆積大小

建置在用戶端 (Blazor Web 應用程式的 .Client 專案或獨立 Blazor WebAssembly 應用程式) 上執行並以行動裝置瀏覽器 (尤其是 iOS 上的 Safari) 為目標的 Blazor 應用程式時,可能需要使用 MSBuild 屬性 EmccMaximumHeapSize 來減少應用程式的最大記憶體。 預設值為 2,147,483,648 個位元組 (該值可能太大),如果應用程式嘗試配置更多記憶體而瀏覽器無法授與它,則會導致應用程式損毀。 下列範例會在 Program 檔案中將該值設為 268,435,456 個位元組:

建置以行動裝置瀏覽器 (尤其是 iOS 上的 Safari) 為目標的 Blazor WebAssembly 應用程式時,可能需要使用 MSBuild 屬性 EmccMaximumHeapSize 來減少應用程式的最大記憶體。 預設值為 2,147,483,648 個位元組 (該值可能太大),如果應用程式嘗試配置更多記憶體而瀏覽器無法授與它,則會導致應用程式損毀。 下列範例會在 Program 檔案中將該值設為 268,435,456 個位元組:

<EmccMaximumHeapSize>268435456</EmccMaximumHeapSize>

如需 Mono/WebAssembly MSBuild 屬性和目標的相關資訊,請參閱 WasmApp.Common.targets (dotnet/runtime GitHub 存放庫)

.NET 組件的 Webcil 封裝格式

Webcil 是適用於 .NET 組件的網頁式封裝格式,其設計是為了讓您能在受限制的網路環境中使用 Blazor WebAssembly。 Webcil 檔案使用標準的 WebAssembly 包裝函式,組件會部署為使用標準 .wasm 副檔名的 WebAssembly 檔案。

當您發行 Blazor WebAssembly 應用程式時,Webcil 是預設的封裝格式。 若要停止使用 Webcil,請在應用程式的專案檔中設定下列 MS Build 屬性:

<PropertyGroup>
  <WasmEnableWebcil>false</WasmEnableWebcil>
</PropertyGroup>

自訂開機資源的載入方式

請使用 loadBootResource API 來自訂開機資源的載入方式。 如需詳細資訊,請參閱 ASP.NET Core Blazor 啟動

壓縮

在發行 Blazor WebAssembly 應用程式時,系統會在發行期間以靜態方式壓縮輸出,以減少應用程式的大小,並去除執行階段的壓縮負荷。 系統會使用下列壓縮演算法:

Blazor 依賴主機來提供適當壓縮的檔案。 在裝載 Blazor WebAssembly 獨立應用程式時,可能需要執行額外的工作以確保系統會提供以靜態方式壓縮的檔案:

Blazor 依賴主機來提供適當壓縮的檔案。 在使用 ASP.NET Core 裝載的Blazor WebAssembly 專案時,主機專案能夠執行內容交涉並提供以靜態方式壓縮的檔案。 在裝載 Blazor WebAssembly 獨立應用程式時,可能需要執行額外的工作以確保系統會提供以靜態方式壓縮的檔案:

  • 若為 IIS web.config 壓縮組態,請參閱 IIS:Brotli 和 Gzip 壓縮一節。
  • 在不支援靜態壓縮檔案內容交涉的靜態裝載解決方案上進行裝載時,請考慮設定應用程式以擷取和解碼 Brotli 壓縮的檔案:

google/brotli GitHub 存放庫取得 JavaScript Brotli 解碼器。 縮小的解碼器檔案會命名為 decode.min.js,可於存放庫的 js 資料夾中找到。

注意

如果縮小的 decode.js 指令碼版本 (decode.min.js) 失敗,請嘗試改用未縮小的版本 (decode.js)。

更新應用程式以使用解碼器。

wwwroot/index.html 檔案中,於 Blazor 的 <script>autostart 設定為 false

<script src="_framework/blazor.webassembly.js" autostart="false"></script>

在 Blazor 的 <script> 標籤後和結尾 </body> 標籤前,新增下列 JavaScript 程式碼 <script> 區塊。

Blazor Web 應用程式:

<script type="module">
  import { BrotliDecode } from './decode.min.js';
  Blazor.start({
    webAssembly: {
      loadBootResource: function (type, name, defaultUri, integrity) {
        if (type !== 'dotnetjs' && location.hostname !== 'localhost' && type !== 'configuration' && type !== 'manifest') {
          return (async function () {
            const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
            if (!response.ok) {
              throw new Error(response.statusText);
            }
            const originalResponseBuffer = await response.arrayBuffer();
            const originalResponseArray = new Int8Array(originalResponseBuffer);
            const decompressedResponseArray = BrotliDecode(originalResponseArray);
            const contentType = type === 
              'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
            return new Response(decompressedResponseArray, 
              { headers: { 'content-type': contentType } });
          })();
        }
      }
    }
  });
</script>

獨立 Blazor WebAssembly:

<script type="module">
  import { BrotliDecode } from './decode.min.js';
  Blazor.start({
    loadBootResource: function (type, name, defaultUri, integrity) {
      if (type !== 'dotnetjs' && location.hostname !== 'localhost' && type !== 'configuration') {
        return (async function () {
          const response = await fetch(defaultUri + '.br', { cache: 'no-cache' });
          if (!response.ok) {
            throw new Error(response.statusText);
          }
          const originalResponseBuffer = await response.arrayBuffer();
          const originalResponseArray = new Int8Array(originalResponseBuffer);
          const decompressedResponseArray = BrotliDecode(originalResponseArray);
          const contentType = type === 
            'dotnetwasm' ? 'application/wasm' : 'application/octet-stream';
          return new Response(decompressedResponseArray, 
            { headers: { 'content-type': contentType } });
        })();
      }
    }
  });
</script>

如需如何載入開機資源的詳細資訊,請參閱 ASP.NET Core Blazor 啟動

若要停用壓縮,請將 CompressionEnabled MSBuild 屬性新增至應用程式的專案檔,並將值設定為 false

<PropertyGroup>
  <CompressionEnabled>false</CompressionEnabled>
</PropertyGroup>

您可以在命令殼層中使用下列語法將 CompressionEnabled 屬性傳遞至 dotnet publish 命令:

dotnet publish -p:CompressionEnabled=false

若要停用壓縮,請將 BlazorEnableCompression MSBuild 屬性新增至應用程式的專案檔,並將值設定為 false

<PropertyGroup>
  <BlazorEnableCompression>false</BlazorEnableCompression>
</PropertyGroup>

您可以在命令殼層中使用下列語法將 BlazorEnableCompression 屬性傳遞至 dotnet publish 命令:

dotnet publish -p:BlazorEnableCompression=false

重寫 URL 以便正確地路由

在 Blazor WebAssembly 應用程式中的頁面元件路由要求不像 Blazor Server 應用程式中的路由要求那麼簡單。 請考慮具有兩個元件的 Blazor WebAssembly 應用程式:

  • Main.razor:會在應用程式的根目錄載入,並包含 About 元件 (href="About") 的連結。
  • About.razorAbout 元件。

使用瀏覽器的網址列要求應用程式預設文件時 (例如 https://www.contoso.com/):

  1. 瀏覽器提出要求。
  2. 傳回預設頁面,這通常是 index.html
  3. index.html 啟動應用程式。
  4. 會載入 Router 元件並轉譯 RazorMain 元件。

在主頁面中,選取 About 元件的連結在用戶端上會有作用,因為 Blazor 路由器會讓瀏覽器不再於網際網路上對 www.contoso.com 提出 About 的要求,並且會自行提供轉譯的 About 元件。 Blazor WebAssembly 應用程式內的所有內部端點要求有相同的運作方式:要求不會在網際網路上對伺服器裝載的資源觸發瀏覽器型要求。 路由器會在內部處理要求。

如果使用瀏覽器之網址列提出對 www.contoso.com/About 的要求,則要求會失敗。 在應用程式的網際網路主機上沒有這類資源存在,因此會傳回「404 - 找不到」的回應。

因為瀏覽器會提出要求給以網際網路為基礎的主機以取得用戶端頁面,所以網頁伺服器和裝載服務必須針對實際上不在伺服器上的資源,將所有要求重新撰寫至 index.html 頁面。 傳回 index.html 時,應用程式的 Blazor 路由器會進行接管,並以正確的資源做出回應。

在部署至 IIS 伺服器時,您可以使用 URL Rewrite Module 搭配應用程式的已發行 web.config 檔案。 如需詳細資訊,請參閱 IIS 一節。

搭配 ASP.NET Core 的已裝載部署

「裝載部署」會將 Blazor WebAssembly 應用程式從在網頁伺服器上執行的 ASP.NET Core 應用程式提供給瀏覽器。

用戶端 Blazor WebAssembly 應用程式會連同伺服器應用程式的任何其他靜態 Web 資產一起發行至伺服器應用程式的 /bin/Release/{TARGET FRAMEWORK}/publish/wwwroot 資料夾。 兩個應用程式會一起部署。 需要有能夠裝載 ASP.NET Core 應用程式的網頁伺服器。 若為裝載部署,Visual Studio 會包含已選取 Hosted 選項 (使用 dotnet new 命令時為 -ho|--hosted) 的 Blazor WebAssembly 應用程式專案範本 (使用 dotnet new 命令時為 blazorwasm 範本)。

如需詳細資訊,請參閱下列文章:

特定平台的架構相依可執行檔裝載部署

若要將裝載的 Blazor WebAssembly 應用程式部署為特定平台的架構相依可執行檔 (非獨立式),請根據使用中的工具使用下列指導。

Visual Studio

系統預設會對所產生的發行設定檔 (.pubxml) 設定獨立式部署。 請確認 Server 專案的發行設定檔包含設定為 false<SelfContained> MSBuild 屬性。

Server 專案 Properties 資料夾中的 .pubxml 發行設定檔內:

<SelfContained>false</SelfContained>

在 [發行] UI 的 [設定] 區域中,使用 [目標執行階段] 設定來設定 執行階段識別碼 (RID),這會在發行設定檔中產生 <RuntimeIdentifier> MSBuild 屬性:

<RuntimeIdentifier>{RID}</RuntimeIdentifier>

在上述組態中,{RID} 預留位置是執行階段識別碼 (RID)

在 [發行] 組態中發行 Server 專案。

注意

您可以使用 .NET CLI 發行具有發行設定檔設定的應用程式,方法是將 /p:PublishProfile={PROFILE} 傳遞至 dotnet publish 命令,其中 {PROFILE} 預留位置是設定檔。 如需詳細資訊,請參閱適用於 ASP.NET Core 應用程式部署的 Visual Studio 發行設定檔 (.pubxml) 文章中的發行設定檔資料夾發行範例兩個章節。 如果您在 dotnet publish 命令 中 (而非在發行設定檔中) 傳遞 RID,請使用 MSBuild 屬性 (/p:RuntimeIdentifier) 搭配命令,而不是搭配 -r|--runtime 選項。

.NET CLI

將設定為 false<SelfContained> MSBuild 屬性放在 Server 專案之專案檔的 <PropertyGroup> 中,以設定獨立式部署:

<SelfContained>false</SelfContained>

重要

SelfContained 屬性必須放在 Server 專案的專案檔中。 使用 --no-self-contained 選項或 MSBuild 屬性 /p:SelfContained=false,無法以 dotnet publish 命令正確設定此屬性。

使用下列任一方法來設定執行階段識別碼 (RID)

  • 選項 1:在 Server 專案的專案檔中,於 <PropertyGroup> 設定 RID:

    <RuntimeIdentifier>{RID}</RuntimeIdentifier>
    

    在上述組態中,{RID} 預留位置是執行階段識別碼 (RID)

    Server 專案的發行 (Release) 組態中發行 (Publish) 應用程式:

    dotnet publish -c Release
    
  • 選項 2:在 dotnet publish 命令中以 MSBuild 屬性 (/p:RuntimeIdentifier) 的形式傳遞 RID,而不是使用 -r|--runtime 選項來傳遞:

    dotnet publish -c Release /p:RuntimeIdentifier={RID}
    

    在上述命令中,{RID} 預留位置是執行階段識別碼 (RID)

如需詳細資訊,請參閱下列文章:

具有多個 Blazor WebAssembly 應用程式的裝載部署

如需詳細資訊,請參閱多個裝載的 ASP.NET Core Blazor WebAssembly 應用程式

獨立部署

「獨立部署」會以一組直接由用戶端要求的靜態檔案形式提供 Blazor WebAssembly 應用程式。 所有靜態檔案伺服器都能提供 Blazor 應用程式。

獨立部署資產會發行至 /bin/Release/{TARGET FRAMEWORK}/publish/wwwroot 資料夾。

Azure App Service

Blazor WebAssembly 應用程式可以部署到 Windows 上的 Azure App Services,其會將應用程式裝載到 IIS 上。

目前不支援將獨立 Blazor WebAssembly 應用程式部署至適用於 Linux 的 Azure App Service。 建議您使用支援此案例的 Azure Static Web Apps 來裝載獨立的 Blazor WebAssembly 應用程式。

Azure 靜態 Web 應用程式

請使用下列任一方法將 Blazor WebAssembly 應用程式部署至 Azure Static Web Apps:

從 Visual Studio 部署

若要從 Visual Studio 部署,請建立 Azure Static Web Apps 的發行設定檔:

  1. 將任何未儲存的工作儲存在專案中,因為過程中可能需要重新啟動 Visual Studio。

  2. 在 Visual Studio 的 [發行] UI 中,選取 [目標]>[Azure]>[特定目標]>[Azure Static Web Apps] 以建立發行設定檔

  3. 如果未安裝 Visual Studio 的 Azure WebJobs 工具元件,則會出現要您安裝 ASP.NET 和 Web 開發元件的提示。 請遵循提示,使用 Visual Studio 安裝程式安裝工具。 Visual Studio 會在安裝工具時自動關閉並重新開啟。 工具安裝好後,請從第一個步驟重新開始以建立發行設定檔。

  4. 在發行設定檔組態中,提供 [訂用帳戶名稱]。 選取現有的執行個體,或選取 [建立新的執行個體]。 在 Azure 入口網站的 [建立靜態 Web 應用程式] UI 中建立新的執行個體時,請將 [部署詳細資料]>[來源] 設定為 [其他]。 等候部署在 Azure 入口網站中完成,再繼續進行。

  5. 在發行設定檔組態中,從執行個體的資源群組中選取 Azure Static Web Apps 執行個體。 選取 [完成] 以建立發行設定檔。 如果 Visual Studio 提示您安裝 Static Web Apps (SWA) CLI,請遵循提示來安裝 CLI。 SWA CLI 需要 NPM/Node.js (Visual Studio 文件)

發行設定檔建立好後,請選取 [發行] 按鈕,使用發行設定檔將應用程式部署至 Azure Static Web Apps 執行個體。

從 GitHub 部署

若要從 GitHub 存放庫部署,請參閱教學課程:在 Azure Static Web Apps 中使用 Blazor 建置靜態 Web 應用程式

IIS

IIS 是足以支援 Blazor 應用程式的靜態檔案伺服器。 若要設定 IIS 來裝載 Blazor,請參閱在 IIS 上建置靜態網站

根據所使用的 SDK 版本以及 {TARGET FRAMEWORK} 預留位置是目標架構的位置,所發行的資產會建立到 /bin/Release/{TARGET FRAMEWORK}/publishbin\Release\{TARGET FRAMEWORK}\browser-wasm\publish 資料夾。 在網頁伺服器或裝載服務上,裝載 publish 資料夾的內容。

web.config

在發行 Blazor 專案時,系統會使用下列 IIS 組態建立 web.config 檔案:

  • MIME 類型
  • 針對下列 MIME 類型會啟用 HTTP 壓縮:
    • application/octet-stream
    • application/wasm
  • 建立 URL Rewrite Module 規則:
    • 提供應用程式靜態資產所在的子目錄 (wwwroot/{PATH REQUESTED})。
    • 建立 SPA 後援路由,讓非檔案資產要求重新導向至其靜態資產資料夾中的應用程式預設文件 (wwwroot/index.html)。

使用自訂的 web.config

若要使用自訂的 web.config 檔案:

  1. 將自訂的 web.config 檔案放到專案的根資料夾。
  2. 發行專案。 如需詳細資訊,請參閱裝載和部署 ASP.NET Core Blazor
  1. 將自訂的 web.config 檔案放到專案的根資料夾。 針對裝載的 Blazor WebAssembly解決方案,請將檔案放到 Server 專案的資料夾。
  2. 發行專案。 針對裝載的 Blazor WebAssembly 解決方案,從 Server 專案發行解決方案。 如需詳細資訊,請參閱裝載和部署 ASP.NET Core Blazor

如果在發行期間,SDK 的 web.config 產生或轉換不會將檔案移至 publish 資料夾中的已發行資產,或修改您自訂 web.config 檔案中的自訂組態,請視需要使用下列任何方法來控制整個過程:

  • 例如,如果 SDK 不會根據所使用的 SDK 版本以及 {TARGET FRAMEWORK} 預留位置是目標架構的位置在獨立 Blazor WebAssembly 應用程式的 /bin/Release/{TARGET FRAMEWORK}/publish/wwwrootbin\Release\{TARGET FRAMEWORK}\browser-wasm\publish 中產生檔案,請在專案檔 (.csproj) 中將 <PublishIISAssets> 屬性設定為 true。 對獨立 WebAssembly 應用程式而言,這通常是移動自訂 web.config 檔案並防止 SDK 轉換檔案的唯一必要設定。

    <PropertyGroup>
      <PublishIISAssets>true</PublishIISAssets>
    </PropertyGroup>
    
  • 在專案檔 (.csproj) 中停用 SDK 的 web.config 轉換:

    <PropertyGroup>
      <IsTransformWebConfigDisabled>true</IsTransformWebConfigDisabled>
    </PropertyGroup>
    
  • 將自訂目標新增至專案檔 (.csproj) 以移動自訂 web.config 檔案。 在下列範例中,開發人員會將自訂 web.config 檔案放到專案的根目錄。 如果 web.config 檔案位於其他地方,請在 SourceFiles 中指定該檔案的路徑。 下列範例會使用 $(PublishDir) 指定 publish 資料夾,但會提供要作為自訂輸出位置的 DestinationFolder 路徑。

    <Target Name="CopyWebConfig" AfterTargets="Publish">
      <Copy SourceFiles="web.config" DestinationFolder="$(PublishDir)" />
    </Target>
    

安裝 URL Rewrite 模組

需要 URL Rewrite Module,才可重寫 URL。 預設不會安裝此模組,且其無法用來安裝為網頁伺服器 (IIS) 角色服務功能。 必須從 IIS 網站下載模組。 請使用 Web Platform Installer 安裝模組:

  1. 在本機上,巡覽至 URL Rewrite Module 下載頁面。 如需英文版,請選取 [WebPI] 下載 WebPI 安裝程式。 如需其他語言,請選取適當的伺服器架構 (x86 x64) 來下載安裝程式。
  2. 將安裝程式複製到伺服器。 執行安裝程式。 選取 [安裝] 按鈕,並接受授權條款。 安裝完成之後,不需要重新啟動伺服器。

設定網站

將網站的 [實體路徑] 設為應用程式的資料夾。 資料夾包含:

  • IIS 用來設定網站的 web.config 檔案,包括必要的重新導向規則和檔案內容類型。
  • 應用程式的靜態資產資料夾。

裝載為 IIS 子應用程式

如果將獨立應用程式裝載為 IIS 子應用程式,請執行下列任一動作:

  • 停用所繼承的 ASP.NET Core 模組處理常式。

    移除 Blazor 應用程式已發行的 web.config 檔案中的處理常式,方法是新增 <handlers> 區段到該檔案的 <system.webServer> 區段:

    <handlers>
      <remove name="aspNetCore" />
    </handlers>
    
  • 使用 <location> 元素,並將 inheritInChildApplications 設定為 false,以停用根 (父系) 應用程式 <system.webServer> 區段的繼承:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <location path="." inheritInChildApplications="false">
        <system.webServer>
          <handlers>
            <add name="aspNetCore" ... />
          </handlers>
          <aspNetCore ... />
        </system.webServer>
      </location>
    </configuration>
    

    注意

    停用根 (父系) 應用程式 <system.webServer> 區段的繼承是使用 .NET SDK 之已發行應用程式的預設組態。

除了設定應用程式的基底路徑外,也會移除處理常式或停用繼承。 在應用程式的 index.html 檔案,將應用程式基底路徑設為在 IIS 中設定子應用程式時使用的 IIS 別名。

請遵循裝載和部署 ASP.NET Core Blazor一文中的指引,設定應用程式的基底路徑。

Brotli 和 Gzip 壓縮

本節僅適用於獨立的 Blazor WebAssembly 應用程式。

本節僅適用於獨立的 Blazor WebAssembly 應用程式。 裝載的 Blazor 應用程式會使用預設 ASP.NET Core 應用程式 web.config 檔案,而不是本節所連結的檔案。

您可以透過 web.config 設定 IIS,以便為獨立的 Blazor WebAssembly 應用程式提供以 Brotli 或 Gzip 壓縮的 Blazor 資產。 如需範例組態檔,請參閱 web.config

下列案例可能需要為範例 web.config 檔案進行其他組態設定:

  • 應用程式的規格會呼叫下列任一項:
    • 提供範例 web.config 檔案未設定的壓縮檔案。
    • 以未壓縮格式提供範例 web.config 檔案所設定的壓縮檔案。
  • 伺服器的 IIS 組態 (例如,applicationHost.config) 會提供伺服器層級的 IIS 預設值。 視伺服器層級的組態而定,應用程式所需要的 IIS 組態可能與範例 web.config 檔案所包含的 IIS 組態不同。

如需自訂 web.config 檔案的詳細資訊,請參閱使用自訂 web.config 一節。

疑難排解

如果收到「500 - 內部伺服器錯誤」,且 IIS 管理員在嘗試存取網站設定時擲回錯誤,請確認是否已安裝 URL Rewrite 模組。 未安裝此模組時,IIS 無法剖析 web.config 檔案。 這導致 IIS 管理員無法載入網站的組態,且網站無法提供 Blazor 的靜態檔案。

如需針對 IIS 部署進行疑難排解的詳細資訊,請參閱針對 Azure App Service 和 IIS 上的 ASP.NET Core 進行疑難排解

Azure 儲存體

Azure 儲存體靜態檔案裝載允許無伺服器的 Blazor 應用程式裝載。 支援自訂網域名稱、Azure 內容傳遞網路 (CDN) 及 HTTPS。

當 Blob 服務針對儲存體帳戶上的靜態網站裝載啟用時:

  • 將 [索引文件名稱] 設定為 index.html
  • 將 [錯誤文件路徑] 設定為 index.html。 Razor 元件和其他非檔案端點不會位於由 Blob 服務所存放之靜態內容中的實體路徑上。 當系統接收到針對這些資源之一,且應由 Blazor 路由器處理的要求時,由 Blob 服務所產生的「404 - 找不到」錯誤會將要求路由至錯誤文件路徑。 系統會傳回 index.html Blob,且 Blazor 路由器會載入並處理該路徑。

如果因為檔案的 Content-Type 標頭中有不適當的 MIME 類型而使得檔案未在執行階段載入,請採取下列任一動作:

  • 設定您的工具,以在部署檔案時設定正確的 MIME 類型 (Content-Type 標頭)。

  • 在應用程式部署好之後,變更檔案的 MIME 類型 (Content-Type 標頭)。

    在每個檔案的儲存體總管 (Azure 入口網站) 中:

    1. 以滑鼠右鍵按一下檔案,然後選取 [屬性]。
    2. 設定 [ContentType],然後選取 [儲存] 按鈕。

如需詳細資訊,請參閱Azure 儲存體中的靜態網站代管

Nginx

下列 nginx.conf 檔案已簡化,示範如何將 Nginx 設定為每當找不到磁碟上的對應檔案時,便傳送 index.html 檔案。

events { }
http {
    server {
        listen 80;

        location / {
            root      /usr/share/nginx/html;
            try_files $uri $uri/ /index.html =404;
        }
    }
}

使用 limit_req 設定 NGINX 高載速率限制時,Blazor WebAssembly 應用程式可能需要大的 burst 參數值,才能容納應用程式所提出的較大量要求。 一開始,請至少將值設定為 60:

http {
    server {
        ...

        location / {
            ...

            limit_req zone=one burst=60 nodelay;
        }
    }
}

如果瀏覽器開發人員工具或網路流量工具指出要求收到 503 - 服務無法使用狀態碼,則請增加此值。

如需生產環境 Nginx 網頁伺服器組態的詳細資訊,請參閱建立 NGINX Plus 和 NGINX 組態檔

CentOS

在 2024 年 6 月 30 日,CentOS 將達到生命週期結束(EOL)狀態,並且將不再支援 Blazor WebAssembly 裝載的 Web 伺服器。 如需詳細資訊,請參閱以下資源:

Apache

若要將 Blazor WebAssembly 應用程式部署至 CentOS 7 或更新版本:

  1. 建立 Apache 組態檔。 下列範例是簡化後的組態檔 (blazorapp.config):
<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias *.example.com

    DocumentRoot "/var/www/blazorapp"
    ErrorDocument 404 /index.html

    AddType application/wasm .wasm

    <Directory "/var/www/blazorapp">
        Options -Indexes
        AllowOverride None
    </Directory>

    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE text/html
        AddOutputFilterByType DEFLATE application/octet-stream
        AddOutputFilterByType DEFLATE application/wasm
        <IfModule mod_setenvif.c>
      BrowserMatch ^Mozilla/4 gzip-only-text/html
      BrowserMatch ^Mozilla/4.0[678] no-gzip
      BrowserMatch bMSIE !no-gzip !gzip-only-text/html
  </IfModule>
    </IfModule>

    ErrorLog /var/log/httpd/blazorapp-error.log
    CustomLog /var/log/httpd/blazorapp-access.log common
</VirtualHost>
<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias *.example.com

    DocumentRoot "/var/www/blazorapp"
    ErrorDocument 404 /index.html

    AddType application/wasm .wasm
    AddType application/octet-stream .dll

    <Directory "/var/www/blazorapp">
        Options -Indexes
        AllowOverride None
    </Directory>

    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE text/html
        AddOutputFilterByType DEFLATE application/octet-stream
        AddOutputFilterByType DEFLATE application/wasm
        <IfModule mod_setenvif.c>
      BrowserMatch ^Mozilla/4 gzip-only-text/html
      BrowserMatch ^Mozilla/4.0[678] no-gzip
      BrowserMatch bMSIE !no-gzip !gzip-only-text/html
  </IfModule>
    </IfModule>

    ErrorLog /var/log/httpd/blazorapp-error.log
    CustomLog /var/log/httpd/blazorapp-access.log common
</VirtualHost>
  1. 將 Apache 組態檔放入 /etc/httpd/conf.d/ 目錄中,這是 CentOS 7 中預設的 Apache 組態目錄。

  2. 將應用程式的檔案放入 /var/www/blazorapp 目錄 (組態檔中指定給 DocumentRoot 的位置)。

  3. 重新啟動 Apache 服務。

如需詳細資訊,請參閱 mod_mimemod_deflate

GitHub Pages

會部署頁面的預設 GitHub Action 會略過以底線開頭之資料夾的部署,例如 _framework 資料夾。 若要部屬以底線開頭的資料夾,請將空白的 .nojekyll 檔案新增至 Git 分支。

Git 會將 blazor.webassembly.js 之類的 JavaScript (JS) 檔案視為文字,並在部署管線中將行尾從 CRLF (歸位字元-換行字元) 轉換為 LF (換行字元)。 JS 檔案的這些變更所產生的檔案雜湊,會與 Blazor 在 blazor.boot.json 檔案中傳送給用戶端的檔案雜湊不同。 兩者不相符的情況會導致用戶端的完整性檢查失敗。 解決此問題的其中一個方法是,在將應用程式的資產新增至 Git 分支之前,先新增有 *.js binary 行的 .gitattributes 檔案。 *.js binary 行會將 Git 設定為將 JS 檔案視為二進位檔案,以避免在部署管線中處理檔案。 未處理檔案的檔案雜湊會符合 blazor.boot.json 檔案中的項目,而且用戶端完整性檢查會通過。 如需詳細資訊,請參閱 ASP.NET Core Blazor WebAssembly .NET 執行階段和應用程式套件組合快取

若要處理 URL 重寫,請新增 wwwroot/404.html 檔案,以及會處理將要求重新導向至 index.html 頁面之作業的指令碼。 如需範例,請參閱 SteveSandersonMS/BlazorOnGitHubPages GitHub 存放庫

使用專案網站而非組織網站時,請在 wwwroot/index.html 中更新 <base> 標籤。 將 href 屬性值設定為 GitHub 存放庫名稱,並在尾端加上斜線 (例如 /my-repository/)。 在 SteveSandersonMS/BlazorOnGitHubPages GitHub 存放庫中,基底 href 會在發佈時由 .github/workflows/main.yml 設定檔更新。

注意

SteveSandersonMS/BlazorOnGitHubPages GitHub 存放庫 不受 .NET Foundation 或 Microsoft 所擁有、維護或支援。

使用 Docker 的獨立應用程式

獨立的 Blazor WebAssembly 應用程式會以一組靜態檔案的形式發行,以便由靜態檔案伺服器裝載。

若要在 Docker 中裝載應用程式:

  • 選擇具有網頁伺服器支援的 Docker 容器,例如 Ngnix 或 Apache。
  • publish 資料夾資產複製到網頁伺服器中所定義、用於提供靜態檔案的位置資料夾。
  • 視需要套用其他組態以提供 Blazor WebAssembly 應用程式。

如需組態方面的指導,請參閱下列資源:

主機組態值

在開發環境中,Blazor WebAssembly 應用程式可以在執行階段接受以下列主機組態值作為命令列引數。

內容根目錄

--contentroot 引數會設定包含應用程式內容檔案的目錄絕對路徑 (內容根目錄)。 在下列範例中,/content-root-path 是應用程式的內容根路徑。

  • 在命令提示字元,於本機執行應用程式時傳遞引數。 從應用程式目錄,執行:

    dotnet run --contentroot=/content-root-path
    
  • IIS Express 設定檔中,新增項目至應用程式的 launchSettings.json 檔案。 此設定的使用時機為當應用程式是搭配 Visual Studio 偵錯工具並以 dotnet run 從命令提示字元執行的情況。

    "commandLineArgs": "--contentroot=/content-root-path"
    
  • 在 Visual Studio 中,在 [屬性]>[偵錯]>[應用程式引數] 中指定引數。 在 Visual Studio 屬性頁中設定引數,會將引數新增至 launchSettings.json 檔案。

    --contentroot=/content-root-path
    

路徑基底

--pathbase 引數會以非根相對 URL 路徑,為本機執行的應用程式設定應用程式基底路徑 (<base> 標籤 href 會設為非 / 的路徑以供預備和生產之用)。 在下列範例中,/relative-URL-path 是應用程式的路徑基底。 如需詳細資訊,請參閱應用程式基底路徑

重要

不同於提供給 <base> 標籤 href 的路徑,在傳遞 --pathbase 引數值時請勿包含尾端的斜線 (/)。 如果應用程式基底路徑提供於 <base> 標籤作為 <base href="/CoolApp/"> (包括尾端的斜線),請將命令列引數值傳遞為 --pathbase=/CoolApp (不含尾端的斜線)。

  • 在命令提示字元,於本機執行應用程式時傳遞引數。 從應用程式目錄,執行:

    dotnet run --pathbase=/relative-URL-path
    
  • IIS Express 設定檔中,新增項目至應用程式的 launchSettings.json 檔案。 此設定的使用時機為當應用程式是搭配 Visual Studio 偵錯工具並以 dotnet run 從命令提示字元執行的情況。

    "commandLineArgs": "--pathbase=/relative-URL-path"
    
  • 在 Visual Studio 中,在 [屬性]>[偵錯]>[應用程式引數] 中指定引數。 在 Visual Studio 屬性頁中設定引數,會將引數新增至 launchSettings.json 檔案。

    --pathbase=/relative-URL-path
    

URL

--urls 引數會搭配要用來接聽要求的連接埠和通訊協定,設定 IP 位址或主機位址。

  • 在命令提示字元,於本機執行應用程式時傳遞引數。 從應用程式目錄,執行:

    dotnet run --urls=http://127.0.0.1:0
    
  • IIS Express 設定檔中,新增項目至應用程式的 launchSettings.json 檔案。 此設定的使用時機為當應用程式是搭配 Visual Studio 偵錯工具並以 dotnet run 從命令提示字元執行的情況。

    "commandLineArgs": "--urls=http://127.0.0.1:0"
    
  • 在 Visual Studio 中,在 [屬性]>[偵錯]>[應用程式引數] 中指定引數。 在 Visual Studio 屬性頁中設定引數,會將引數新增至 launchSettings.json 檔案。

    --urls=http://127.0.0.1:0
    

Linux 上的裝載部署 (Nginx)

遵循設定 ASP.NET Core 以與 Proxy 伺服器和負載平衡器搭配運作中的指導,使用 ForwardedHeadersOptions 設定應用程式以轉送 X-Forwarded-ForX-Forwarded-Proto 標頭。

如需如何設定應用程式基底路徑的詳細資訊 (包括子應用程式的路徑組態),請參閱裝載和部署 ASP.NET CoreBlazor

遵循 ASP.NET Core SignalR 應用程式的指導,並進行下列變更:

  • 移除 Proxy 緩衝的組態 (proxy_buffering off;),因為此設定僅適用於伺服器傳送的事件 (SSE),而這與 Blazor 應用程式的用戶端伺服器互動無關。

  • location 路徑從 /hubroute (location /hubroute { ... }) 變更為子應用程式的路徑 /{PATH} (location /{PATH} { ... }),其中 {PATH} 預留位置是子應用程式的路徑。

    下列範例會在根路徑 / 為回應要求的應用程式設定伺服器:

    http {
        server {
            ...
            location / {
                ...
            }
        }
    }
    

    下列範例會設定 /blazor 的子應用程式路徑:

    http {
        server {
            ...
            location /blazor {
                ...
            }
        }
    }
    

如需詳細資訊和組態方面的指導,請參閱下列資源:

設定修剪器

Blazor 會在每個發行組建上執行中繼語言 (IL) 修剪,以從輸出組件中移除不必要的 IL。 如需詳細資訊,請參閱設定 ASP.NET Core Blazor 的修剪器

設定連結器

Blazor 會在每個發行組建上執行中繼語言 (IL) 連結,以從輸出組件中移除不必要的 IL。 如需詳細資訊,請參閱設定 ASP.NET Core Blazor 的連結器

變更 DLL 檔案的副檔名

本節適用於 ASP.NET Core 6.x 和 7.x。 在 .NET 8 或更新版本中的 ASP.NET Core 中,.NET 組件會使用 Webcil 檔案格式部署為 WebAssembly 檔案 (.wasm)。 在 .NET 8 或更新版本中的 ASP.NET Core 中,只有在應用程式的專案檔中已停用 Webcil 檔案格式時,本節的內容才會適用。

如果防火牆、防毒程式或網路安全性設備會封鎖應用程式動態連結程式庫 (DLL) 檔案 .dll 的傳輸,您可以遵循本節中的指導來變更應用程式已發行 DLL 檔案的副檔名。

注意

變更應用程式 DLL 檔案的副檔名可能無法解決問題,因為許多安全性系統會掃描應用程式檔案的內容,而不只是檢查副檔名。

針對會封鎖 DLL 檔案下載和執行的環境,如需更健全的方法,請使用 .NET 8 或更新版本中的 ASP.NET Core,其預設會使用 WebCil 檔案格式將 .NET 組件封裝為 WebAssembly 檔案 (.wasm)。 如需詳細資訊,請參閱本文 8.0 或更新版本中 .NET 組件的 Webcil 封裝格式一節。

協力廠商也有可處理此問題的方法。 如需詳細資訊,請參閱 Awesome Blazor 上的資源。

注意

變更應用程式 DLL 檔案的副檔名可能無法解決問題,因為許多安全性系統會掃描應用程式檔案的內容,而不只是檢查副檔名。

針對會封鎖 DLL 檔案下載和執行的環境,如需更健全的方法,請採用下列任一方法:

  • 使用 .NET 8 或更新版本中的 ASP.NET Core,其預設會使用 WebCil 檔案格式將 .NET 組件封裝為 WebAssembly 檔案 (.wasm)。 如需詳細資訊,請參閱本文 8.0 或更新版本中 .NET 組件的 Webcil 封裝格式一節。
  • 在 .NET 6 或更新版本中的 ASP.NET Core 中,使用自訂部署配置

協力廠商也有可處理此問題的方法。 如需詳細資訊,請參閱 Awesome Blazor 上的資源。

在發行應用程式後,請使用殼層指令碼或 DevOps 建置管線來重新命名 .dll 檔案,以在應用程式已發行輸出的目錄中使用不同的副檔名。

在下列範例中:

  • 會使用 PowerShell (PS) 來更新副檔名。
  • 會從命令列重新命名 .dll 檔案,以使用 .bin 副檔名。
  • 已發行 blazor.boot.json 檔案中所列出具有 .dll 副檔名的檔案會更新為 .bin 副檔名。
  • 如果服務背景工作角色資產也正在使用中,PowerShell 命令會將 service-worker-assets.js 檔案中列出的 .dll 檔案更新為 .bin 副檔名。

若要使用與 .bin 不同的副檔名,請使用所需的副檔名取代下列命令中的 .bin

在 Windows 上:

dir {PATH} | rename-item -NewName { $_.name -replace ".dll\b",".bin" }
((Get-Content {PATH}\blazor.boot.json -Raw) -replace '.dll"','.bin"') | Set-Content {PATH}\blazor.boot.json

在上述命令中,{PATH} 預留位置是已發行 _framework 資料夾的路徑 (例如,來自專案根資料夾的 .\bin\Release\net6.0\browser-wasm\publish\wwwroot\_framework)。

如果服務背景工作角色資產也正在使用中:

((Get-Content {PATH}\service-worker-assets.js -Raw) -replace '.dll"','.bin"') | Set-Content {PATH}\service-worker-assets.js

在上述命令中,{PATH} 預留位置是已發行 service-worker-assets.js 檔案的路徑。

在 Linux 或 macOS 上:

for f in {PATH}/*; do mv "$f" "`echo $f | sed -e 's/\.dll/.bin/g'`"; done
sed -i 's/\.dll"/.bin"/g' {PATH}/blazor.boot.json

在上述命令中,{PATH} 預留位置是已發行 _framework 資料夾的路徑 (例如,來自專案根資料夾的 .\bin\Release\net6.0\browser-wasm\publish\wwwroot\_framework)。

如果服務背景工作角色資產也正在使用中:

sed -i 's/\.dll"/.bin"/g' {PATH}/service-worker-assets.js

在上述命令中,{PATH} 預留位置是已發行 service-worker-assets.js 檔案的路徑。

若要處理壓縮的 blazor.boot.json.gzblazor.boot.json.br 檔案,請採用下列任一方法:

  • 移除壓縮的 blazor.boot.json.gzblazor.boot.json.br 檔案。 使用此方法會停用壓縮。
  • 重新壓縮更新後的 blazor.boot.json 檔案。

當服務背景工作角色資產正在使用時,則上述的已壓縮 blazor.boot.json 檔案的指導也會適用。 請移除或重新壓縮 service-worker-assets.js.brservice-worker-assets.js.gz。 否則,瀏覽器的檔案完整性檢查會失敗。

下列適用於 .NET 6 的 Windows 範例會使用放在專案根目錄的 PowerShell 指令碼。 如果您想要重新壓縮 blazor.boot.json 檔案,下列會停用壓縮的指令碼是您進行進一步修改的基礎。

ChangeDLLExtensions.ps1:

param([string]$filepath,[string]$tfm)
dir $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework | rename-item -NewName { $_.name -replace ".dll\b",".bin" }
((Get-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json -Raw) -replace '.dll"','.bin"') | Set-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json.gz
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\blazor.boot.json.br

如果服務背景工作角色資產也正在使用中,請新增下列命令:

((Get-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\service-worker-assets.js -Raw) -replace '.dll"','.bin"') | Set-Content $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\wwwroot\service-worker-assets.js
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\wwwroot\service-worker-assets.js.gz
Remove-Item $filepath\bin\Release\$tfm\browser-wasm\publish\wwwroot\_framework\wwwroot\service-worker-assets.js.br

在專案檔中,指令碼會在發行 Release 組態的應用程式後執行:

<Target Name="ChangeDLLFileExtensions" AfterTargets="AfterPublish" Condition="'$(Configuration)'=='Release'">
  <Exec Command="powershell.exe -command &quot;&amp; { .\ChangeDLLExtensions.ps1 '$(SolutionDir)' '$(TargetFramework)'}&quot;" />
</Target>

注意

在重新命名和延後載入相同組件時,請參閱 ASP.NET Core Blazor WebAssembly 中的延後載入組件中的指導。

應用程式的伺服器通常需要靜態資產組態,才能以更新後的副檔名提供檔案。 針對 IIS 所裝載的應用程式,在自訂 web.config 檔案的靜態內容區段 (<staticContent>) 中新增新副檔名的 MIME 對應項目 (<mimeMap>)。 下列範例假設副檔名已從 .dll 變更為 .bin

<staticContent>
  ...
  <mimeMap fileExtension=".bin" mimeType="application/octet-stream" />
  ...
</staticContent>

如果有使用壓縮,請包含壓縮檔案的更新:

<mimeMap fileExtension=".bin.br" mimeType="application/octet-stream" />
<mimeMap fileExtension=".bin.gz" mimeType="application/octet-stream" />

移除 .dll 副檔名的項目:

- <mimeMap fileExtension=".dll" mimeType="application/octet-stream" />

如果有使用壓縮,請移除壓縮後 .dll 檔案的項目:

- <mimeMap fileExtension=".dll.br" mimeType="application/octet-stream" />
- <mimeMap fileExtension=".dll.gz" mimeType="application/octet-stream" />

如需自訂 web.config 檔案的詳細資訊,請參閱使用自訂 web.config 一節。

先前的部署損毀

一般來說,在部署時:

  • 只會取代已變更的檔案,這通常會導致部署速度加快。
  • 不屬於新部署的現有檔案會就地保留,以供新部署使用。

在極少數情況下,一直留在先前部署中的檔案可能會損毀新的部署。 徹底刪除現有部署 (或在部署前刪除本機發行的應用程式) 可能會解決部署損毀的問題。 刪除現有部署一次往往就足以解決問題,DevOps 的建置和部署管線也是如此。

如果您判斷在使用 DevOps 建置和部署管線時,一律需要清除先前的部署,則可以暫時在建置管線中新增步驟以刪除每個新部署的先前部署,直到您針對損毀的確切原因進行疑難排解為止。

解決完整性檢查失敗

Blazor WebAssembly 在下載應用程式的啟動檔案時,會指示瀏覽器對回應執行完整性檢查。 Blazor 會針對 DLL (.dll)、WebAssembly (.wasm) 和 blazor.boot.json 檔案中的其他檔案傳送 SHA-256 雜湊值,但用戶端上不會快取這些檔案。 所快取檔案的檔案雜湊會與 blazor.boot.json 檔案中的雜湊進行比較。 對於具有相符雜湊的快取檔案,Blazor 會使用快取的檔案。 否則,系統會向伺服器要求檔案。 檔案下載完成後,系統會再次檢查其雜湊以驗證完整性。 如果任何所下載檔案的完整性檢查失敗,瀏覽器就會產生錯誤。

Blazor 用於管理檔案完整性的演算法:

  • 確保應用程式不會有載入一組不一致檔案的風險,例如,在使用者正在下載應用程式檔時,將新的部署套用至您的網頁伺服器的話。 檔案不一致可能會導致應用程式故障。
  • 確保使用者的瀏覽器永遠不會快取不一致或無效的回應,即使使用者手動重新整理頁面,這也可能會導致應用程式無法啟動。
  • 在預期的 SHA-256 雜湊本身變更之前,讓其可以安全地快取回應,且不會檢查伺服器端變更,以便後續的頁面載入涉及較少的要求,並更快地完成。

如果網頁伺服器傳回不符合預期 SHA-256 雜湊的回應,則瀏覽器開發人員主控台中會出現類似下列範例的錯誤:

針對具有已計算 SHA-256 完整性 'IIa70iwvmEg5WiDV17OpQ5eCztNYqL186J56852RpJY=' 的資源 'https://myapp.example.com/_framework/MyBlazorApp.dll',在其 'integrity' 屬性中找不到有效的摘要。 該資源已遭到封鎖。

在大部分情況下,該警告並非代表完整性檢查有問題。 相反地,該警告通常表示存在一些其他問題。

如需 Blazor WebAssembly 的開機參考來源,請參閱 dotnet/aspnetcore GitHub 存放庫中的 Boot.WebAssembly.ts 檔案

注意

.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤

診斷完整性問題

在建置應用程式時,產生的 blazor.boot.json 資訊清單會描述產生建置輸出時開機資源的 SHA-256 雜湊。 只要 blazor.boot.json 中的 SHA-256 雜湊符合傳遞至瀏覽器的檔案,完整性檢查就會通過。

檢查失敗的常見原因包括:

  • 網頁伺服器的回應是一個錯誤 (例如,404 - 找不到500 - 內部伺服器錯誤),而不是瀏覽器所要求的檔案。 瀏覽器會將這回報為完整性檢查失敗,而不是回應失敗。
  • 某些項目導致檔案內容在檔案建置時和檔案傳遞至瀏覽器時發生了變更。 可能導致此情況的原因為:
    • 如果您或建置工具手動修改建置輸出。
    • 如果部署程序的某些方面修改了檔案。 例如,如果您使用 Git 型部署機制,請記住,如果您認可 Windows 上的檔案,並在 Linux 上將檔案簽出,Git 會以透明的方式將 Windows 樣式的行尾轉換成 Unix 樣式的行尾。 變更檔案行尾就會變更 SHA-256 雜湊。 若要避免此問題,請考慮使用 .gitattributes 將組建成品視為 binary 檔案
    • 網頁伺服器會在提供檔案內容時修改檔案內容。 例如,某些內容散發網路 (CDN) 會自動嘗試縮製 HTML,藉此修改 HTML。 您可能需要停用這類功能。
  • blazor.boot.json 檔案無法正確載入或在用戶端上以不正確的方式加以快取。 常見原因包括下列任一項:
    • 設定錯誤或故障的自訂開發人員程式碼。
    • 一或多個設定錯誤的中繼快取層。

若要診斷您的案例適用上述哪一項:

  1. 讀取錯誤訊息以記下是哪一個檔案觸發錯誤。
  2. 開啟瀏覽器的開發人員工具,並查看 [網路] 索引標籤。如有必要,請重新載入頁面以查看要求和回應的清單。 在該清單中尋找觸發錯誤的檔案。
  3. 檢查回應中的 HTTP 狀態碼。 如果伺服器傳回 200 - 正常以外的任何錯誤 (或其他 2xx 狀態碼),則表示您有伺服器端問題需要診斷。 例如,狀態碼 403 表示發生授權問題,而狀態碼 500 表示伺服器以未指定的方式失敗。 請參閱伺服器端記錄以診斷和修正應用程式。
  4. 如果資源的狀態碼為 200 - 正常,請查看瀏覽器開發人員工具中的回應內容,並檢查內容是否符合預期的資料。 例如,常見的問題是路由設定錯誤,使得即使是其他檔案的要求也傳回您的 index.html 資料。 請確定 .wasm 要求的回應是 WebAssembly 二進位檔,而 .dll 要求的回應是 .NET 組件二進位檔。 如果不是,則表示您有伺服器端的路由問題需要診斷。
  5. 使用針對完整性 PowerShell 指令碼進行疑難排解來設法驗證應用程式的已發行和已部署輸出。

如果您確認伺服器傳回看似合理的正確資料,則表示檔案的建置和傳遞之間必定有其他某些項目修改了內容。 若要調查此情況:

  • 檢查建置工具鏈和部署機制,以免其在檔案建置完成後修改檔案。 此情況的其中一個範例是當 Git 轉換檔案行尾時,如先前所述。
  • 檢查網頁伺服器或 CDN 組態,以免其設定為動態修改回應 (例如,嘗試縮製 HTML)。 網頁伺服器可以實作 HTTP 壓縮 (例如,傳回 content-encoding: brcontent-encoding: gzip),因為這不會影響解壓縮後的結果。 不過,網頁伺服器不能修改未壓縮的資料。

針對完整性 PowerShell 指令碼進行疑難排解

使用 integrity.ps1 PowerShell 指令碼來驗證已發行和已部署的 Blazor 應用程式。 這個指令碼會提供給 PowerShell Core 7 或更新版本,以作為應用程式有 Blazor 架構所無法識別的完整性問題時的解決起點。 這個指令碼可能需要針對您的應用程式加以自訂,如果在 7.2.0 版之後的 PowerShell 版本上執行的話也是如此。

這個指令碼會檢查 publish 資料夾中的檔案,並從已部署的應用程式下載,以偵測包含完整性雜湊的不同資訊清單中的問題。 這些檢查應該能偵測出最常見的問題:

  • 您修改了已發行輸出中的檔案,卻沒注意到。
  • 應用程式未以正確方式部署至部署目標,或部署目標的環境內發生了某些變更。
  • 已部署的應用程式與發行應用程式時所產生的輸出之間有差異。

在 PowerShell 命令殼層中使用下列命令叫用指令碼:

.\integrity.ps1 {BASE URL} {PUBLISH OUTPUT FOLDER}

在下列範例中,指令碼會在 https://localhost:5001/ 於本機執行的應用程式上執行:

.\integrity.ps1 https://localhost:5001/ C:\TestApps\BlazorSample\bin\Release\net6.0\publish\

預留位置:

  • {BASE URL}:已部署應用程式的 URL。 必須有尾端斜線 (/)。
  • {PUBLISH OUTPUT FOLDER}:應用程式的 publish 資料夾或發行應用程式以進行部署之所在位置的路徑。

注意

在複製 dotnet/AspNetCore.Docs GitHub 存放庫時,integrity.ps1 指令碼可能會遭到 Bitdefender 或系統上存在的其他病毒掃描程式隔離。 該檔案通常會被病毒掃描程式的啟發式掃描技術所截獲,因為該技術只會尋找檔案中可能表示有惡意程式碼存在的模式。 若要防止病毒掃描程式隔離檔案,請在複製存放庫之前,於病毒掃描程式中新增例外狀況。 下列範例是該指令碼在 Windows 系統上的典型路徑。 若為其他系統,請視需要調整路徑。 預留位置 {USER} 是使用者的路徑線段。

C:\Users\{USER}\Documents\GitHub\AspNetCore.Docs\aspnetcore\blazor\host-and-deploy\webassembly\_samples\integrity.ps1

警告建立病毒掃描程式例外狀況是危險行為,請只在您確定檔案安全無虞時才這麼做。

比較檔案總和檢查碼的值與有效總和檢查碼的值並無法保證檔案安全無虞,但對惡意使用者來說,以維護總和檢查碼值的方式修改檔案並不是件簡單的事。 因此,將總和檢查碼作為一般的安全性方法會有用。 比較本機 integrity.ps1 檔案的總和檢查碼與下列其中一個值:

  • SHA256:32c24cb667d79a701135cb72f6bae490d81703323f61b8af2c7e5e5dc0f0c2bb
  • MD5:9cee7d7ec86ee809a329b5406fbf21a8

使用下列命令取得檔案在 Windows OS 上的總和檢查碼。 針對 {PATH AND FILE NAME} 預留位置提供路徑和檔案名稱,並指出要為 {SHA512|MD5} 預留位置產生的總和檢查碼類型 (SHA256MD5):

CertUtil -hashfile {PATH AND FILE NAME} {SHA256|MD5}

如果您有任何理由擔心環境中的總和檢查碼驗證不夠安全,請向組織的安全性主管請教以尋求指導。

如需詳細資訊,請參閱 Microsoft Defender 防病毒軟體的威脅防護概觀 (英文)。

停用非 PWA 應用程式的完整性檢查

在大部分情況下,請勿停用完整性檢查。 停用完整性檢查並無法解決造成非預期回應的基礎問題,而且會導致您失去先前列出的好處。

在某些情況下,您無法信賴網頁伺服器會傳回一致的回應,此時您別無選擇,只能暫時停用完整性檢查,直到解決基礎問題為止。

若要停用完整性檢查,請將下列內容新增至 Blazor WebAssembly 應用程式專案檔 (.csproj) 中的屬性群組:

<BlazorCacheBootResources>false</BlazorCacheBootResources>

BlazorCacheBootResources 也會根據檔案的 SHA-256 雜湊來停用 Blazor 預設的快取 .dll.wasm 和其他檔案的行為,因為該屬性指出 SHA-256 雜湊的正確性不值得信賴。 即使使用此設定,瀏覽器的一般 HTTP 快取仍可能會快取這些檔案,但是否會發生此情況取決於網頁伺服器的組態及其提供的 cache-control 標頭。

注意

BlazorCacheBootResources 屬性不會停用漸進式 Web 應用程式 (PWA) 的完整性檢查。 如需有關 PWA 的指導,請參閱停用 PWA 的完整性檢查一節。

我們無法完整提供需要停用完整性檢查的案例清單。 伺服器能以超出 Blazor 架構範圍的任意方式回應要求。 此架構會提供 BlazorCacheBootResources 設定來讓應用程式能夠執行,但代價是會失去應用程式可以提供的完整性保證。 再次重申,不建議您停用完整性檢查,尤其是在生產部署上。 開發人員應設法解決導致完整性檢查失敗的基礎完整性問題才對。

一些可能導致完整性問題的一般案例如下:

  • 在無法檢查完整性的 HTTP 上執行。
  • 如果您的部署程序以任何方式修改發行後的檔案。
  • 如果您的主機以任何方式修改檔案。

停用 PWA 的完整性檢查

Blazor 的漸進式 Web 應用程式 (PWA) 範本包含建議的 service-worker.published.js 檔案,此檔案負責擷取和儲存應用程式檔案以供離線使用。 這是與一般應用程式啟動機制不同的程序,並有自己的個別完整性檢查邏輯。

service-worker.published.js 檔案內有下面這行:

.map(asset => new Request(asset.url, { integrity: asset.hash }));

若要停用完整性檢查,請將這行變更為下列內容,以移除 integrity 參數:

.map(asset => new Request(asset.url));

再次重申,停用完整性檢查表示您會失去完整性檢查所提供的安全性保證。 例如,如果使用者的瀏覽器在您部署新版本時恰好快取應用程式,則會有其可能從舊部署快取一些檔案,並從新部署快取一些檔案的風險。 如果發生這種情況,應用程式會卡在中斷狀態,直到您部署進一步的更新為止。