Teilen über


Bereitstellungslayout für ASP.NET Core gehostete Blazor WebAssembly Apps

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Die aktuelle Version finden Sie in der .NET 10-Version dieses Artikels.

Warnung

Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der .NET- und .NET Core-Supportrichtlinie. Informationen zum aktuellen Release finden Sie in der .NET 9-Version dieses Artikels.

In diesem Artikel wird erläutert, wie Sie gehostete Blazor WebAssembly Bereitstellungen in Umgebungen aktivieren, die den Download und die Ausführung von DLL-Dateien (Dynamic Link Library) blockieren.

Hinweis

Dieser Leitfaden bezieht sich auf Umgebungen, die Clients am Herunterladen und Ausführen von DLLs hindern. In .NET 8 oder höher verwendet Blazor das Webcil-Dateiformat, um dieses Problem zu beheben. Weitere Informationen finden Sie unter ASP.NET Core hosten und bereitstellenBlazor WebAssembly. Die mehrteilige Bündelung mit dem experimentellen NuGet-Paket, das in diesem Artikel beschrieben wird, wird für Blazor Apps in .NET 8 oder höher nicht unterstützt. Sie können die Anleitung in diesem Artikel verwenden, um ein eigenes mehrteiliges NuGet-Bündelungspaket für .NET 8 oder höher zu erstellen.

Blazor WebAssembly Apps benötigen DLLs (Dynamic Link Libraries), um zu funktionieren, aber einige Umgebungen blockieren Clients am Herunterladen und Ausführen von DLLs. Sicherheitsprodukte sind häufig in der Lage, den Inhalt von Dateien zu scannen, die das Netzwerk durchlaufen, und DLL-Dateien zu blockieren oder unter Quarantäne zu stellen. In diesem Artikel wird ein Ansatz zum Aktivieren Blazor WebAssembly von Apps in diesen Umgebungen beschrieben, bei dem eine mehrteilige Paketdatei aus den DLLs der App erstellt wird, sodass die DLLs unter Umgehung von Sicherheitseinschränkungen zusammen heruntergeladen werden können.

Blazor WebAssembly Apps benötigen DLLs (Dynamic Link Libraries), um zu funktionieren, aber einige Umgebungen blockieren Clients am Herunterladen und Ausführen von DLLs. In einer Teilmenge dieser Umgebungen reicht es aus, die Dateinamenerweiterung von DLL-Dateien (.dll) zu ändern, um Sicherheitseinschränkungen zu umgehen, aber Sicherheitsprodukte sind häufig in der Lage, den Inhalt von Dateien zu scannen, die das Netzwerk durchlaufen, und DLL-Dateien zu blockieren oder unter Quarantäne zu stellen. In diesem Artikel wird ein Ansatz zum Aktivieren Blazor WebAssembly von Apps in diesen Umgebungen beschrieben, bei dem eine mehrteilige Paketdatei aus den DLLs der App erstellt wird, sodass die DLLs unter Umgehung von Sicherheitseinschränkungen zusammen heruntergeladen werden können.

Eine gehostete Blazor WebAssembly App kann ihre veröffentlichten Dateien und das Verpacken von App-DLLs mithilfe der folgenden Features anpassen:

  • JavaScript-Initialisierer , die das Anpassen des Blazor Bootvorgangs ermöglichen.
  • MSBuild-Erweiterbarkeit, um die Liste der veröffentlichten Dateien zu transformieren und Veröffentlichungserweiterungen zu definierenBlazor. Blazor Veröffentlichungserweiterungen sind Dateien, die während des Veröffentlichungsprozesses definiert werden und eine alternative Darstellung für den Satz von Dateien bieten, der zum Ausführen einer veröffentlichten Blazor WebAssembly App erforderlich ist. In diesem Artikel wird eine Blazor Veröffentlichungserweiterung erstellt, die ein mehrteiliges Bundle erstellt, in dem alle DLLs der App in einer einzigen Datei gepackt sind, damit die DLLs zusammen heruntergeladen werden können.

Der in diesem Artikel gezeigte Ansatz dient als Ausgangspunkt für Entwickler, um ihre eigenen Strategien und benutzerdefinierten Ladeprozesse zu entwickeln.

Warnung

Jeder Ansatz zur Umgehung einer Sicherheitsbeschränkung muss sorgfältig auf seine Auswirkungen auf die Sicherheit hin abgewogen werden. Es wird empfohlen, das Thema mit den Netzwerksicherheitsexperten Ihrer Organisation weiter zu untersuchen, bevor Sie den Ansatz in diesem Artikel übernehmen. Zu den Alternativen, die Sie in Betracht ziehen sollten, gehören:

  • Aktivieren Sie Sicherheits-Appliances und Sicherheitssoftware, um Netzwerk-Clients das Herunterladen und Verwenden genau der Dateien zu ermöglichen, die für eine Blazor WebAssembly App erforderlich sind.
  • Wechseln Sie vom Blazor WebAssembly Hostingmodell zum Hostingmodell, bei dem Blazor Serverder gesamte C#-Code der App auf dem Server verwaltet wird und keine DLLs auf Clients heruntergeladen werden müssen. Blazor Server bietet auch den Vorteil, dass C#-Code privat bleibt, ohne dass die Verwendung von Web-API-Apps für den Datenschutz von C#-Code bei Blazor WebAssembly Apps erforderlich ist.

Experimentelles NuGet-Paket und Beispiel-App

Der in diesem Artikel beschriebene Ansatz wird vom experimentellenMicrosoft.AspNetCore.Components.WebAssembly.MultipartBundle Paket (NuGet.org) für Apps verwendet, die auf .NET 6 oder höher ausgerichtet sind. Das Paket enthält MSBuild-Ziele zum Anpassen der Blazor Veröffentlichungsausgabe und einen JavaScript-Initialisierer zum Verwenden eines benutzerdefinierten Startressourcenladeprogramms, die weiter unten in diesem Artikel ausführlich beschrieben werden.

Warnung

Experimentier- und Vorschaufunktionen werden zum Sammeln von Feedback bereitgestellt und für die Verwendung in der Produktion nicht unterstützt.

Weiter unten in diesem Artikel enthält der Abschnitt Anpassen des Blazor WebAssembly Ladevorgangs über ein NuGet-Paket mit seinen drei Unterabschnitten ausführliche Erläuterungen zur Konfiguration und zum Code im Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle Paket. Die detaillierten Erklärungen sind wichtig zu verstehen, wenn Sie Ihre eigene Strategie und Ihren eigenen benutzerdefinierten Ladeprozess für Blazor WebAssembly Apps erstellen. Führen Sie die folgenden Schritte aus, um das veröffentlichte, experimentelle, nicht unterstützte NuGet-Paket ohne Anpassung als lokale Demonstration zu verwenden:

  1. Verwenden Sie eine vorhandene gehostete Blazor WebAssemblyProjektmappe , oder erstellen Sie eine neue Projektmappe aus der Blazor WebAssembly Projektvorlage, indem Sie Visual Studio verwenden oder die -ho|--hosted Option an den dotnet new Befehl (dotnet new blazorwasm -ho) übergeben. Weitere Informationen finden Sie unter Tooling for ASP.NET Core Blazor.

  2. Fügen Sie im Client Projekt das experimentelle Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle Paket hinzu.

    Hinweis

    Eine Anleitung zum Hinzufügen von Paketen zu .NET-Anwendungen finden Sie in den Artikeln unter Pakete installieren und verwalten unter Workflow für die Paketnutzung (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.

  3. Fügen Sie im Server Projekt einen Endpunkt für die Bereitstellung der Bundle-Datei hinzu (app.bundle). Beispielcode finden Sie im Abschnitt Bereitstellen des Pakets über die Hostserver-App in diesem Artikel.

  4. Veröffentlichen Sie die App in der Releasekonfiguration.

Anpassen des Blazor WebAssembly Ladevorgangs über ein NuGet-Paket

Warnung

Die Anleitung in diesem Abschnitt mit seinen drei Unterabschnitten bezieht sich auf das Erstellen eines NuGet-Pakets von Grund auf neu, um Ihre eigene Strategie und Ihren benutzerdefinierten Ladeprozess zu implementieren. Das experimentelleMicrosoft.AspNetCore.Components.WebAssembly.MultipartBundle Paket (NuGet.org) für .NET 6 und 7 basiert auf den Anleitungen in diesem Abschnitt. Wenn Sie das bereitgestellte Paket in einer lokalen Demonstration des Ansatzes für den mehrteiligen Bundle-Download verwenden, müssen Sie die Anweisungen in diesem Abschnitt nicht befolgen. Eine Anleitung zur Verwendung des bereitgestellten Pakets finden Sie im Abschnitt Experimentelles NuGet-Paket und Beispiel-App .

Blazor App-Ressourcen werden in eine mehrteilige Bundle-Datei gepackt und vom Browser über einen benutzerdefinierten JavaScript-Initialisierer (JS) geladen. Für eine App, die das Paket mit dem JS Initialisierer nutzt, erfordert die App nur, dass die Bundle-Datei bereitgestellt wird, wenn sie angefordert wird. Alle anderen Aspekte dieses Ansatzes werden transparent gehandhabt.

Für das Laden einer standardmäßig veröffentlichten Blazor App sind vier Anpassungen erforderlich:

  • Eine MSBuild-Aufgabe zum Transformieren der Veröffentlichungsdateien.
  • Ein NuGet-Paket mit MSBuild-Zielen, das sich in den Blazor Veröffentlichungsprozess einklinkt, die Ausgabe transformiert und eine oder mehrere Blazor Veröffentlichungserweiterungsdateien (in diesem Fall ein einzelnes Bundle) definiert.
  • Ein JS Initialisierer zum Aktualisieren des Blazor WebAssembly Ressourcenladeprogramm-Callbacks, sodass das Bundle geladen und die einzelnen Dateien für die App bereitgestellt werden.
  • Ein Helfer in der Host-App Server , um sicherzustellen, dass das Bundle auf Anforderung für Clients bereitgestellt wird.

Erstellen Sie eine MSBuild-Aufgabe, um die Liste der veröffentlichten Dateien anzupassen und neue Erweiterungen zu definieren.

Erstellen Sie eine MSBuild-Aufgabe als öffentliche C#-Klasse, die als Teil einer MSBuild-Kompilierung importiert werden kann und mit dem Build interagieren kann.

Für die C#-Klasse ist Folgendes erforderlich:

Hinweis

Das NuGet-Paket für die Beispiele in diesem Artikel ist nach dem von Microsoft bereitgestellten Paket benannt. Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle Anleitungen zum Benennen und Erstellen eines eigenen NuGet-Pakets finden Sie in den folgenden NuGet-Artikeln:

Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks.csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <LangVersion>8.0</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Build.Framework" Version="{VERSION}" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="{VERSION}" />
  </ItemGroup>

</Project>

Ermitteln Sie die neuesten Paketversionen für die {VERSION} Platzhalter bei NuGet.org:

Um die MSBuild-Aufgabe zu erstellen, erstellen Sie eine öffentliche C#-Klasse, die erweitert Microsoft.Build.Utilities.Task (nicht System.Threading.Tasks.Task), und deklarieren Sie drei Eigenschaften:

  • PublishBlazorBootStaticWebAsset: Die Liste der Dateien, die für die Blazor App veröffentlicht werden sollen.
  • BundlePath: Der Pfad, in den das Bundle geschrieben wird.
  • Extension: Die neuen Veröffentlichungserweiterungen, die in den Build aufgenommen werden sollen.

Die folgende Beispielklasse BundleBlazorAssets ist ein Ausgangspunkt für weitere Anpassungen:

  • In der Execute Methode wird das Bundle aus den folgenden drei Dateitypen erstellt:
    • JavaScript-Dateien (dotnet.js)
    • WebAssembly (Wasm)-Dateien (dotnet.wasm)
    • App-DLLs (.dll)
  • Ein multipart/form-data Bundle wird erstellt. Jede Datei wird dem Bundle mit ihren jeweiligen Beschreibungen über den Content-Disposition-Header und den Content-Type-Header hinzugefügt.
  • Nachdem das Bundle erstellt wurde, wird das Bundle in eine Datei geschrieben.
  • Der Build ist für die Erweiterung konfiguriert. Mit dem folgenden Code wird ein Erweiterungselement erstellt und der Extension Eigenschaft hinzugefügt. Jedes Erweiterungselement enthält drei Datenelemente:
    • Der Pfad zur Erweiterungsdatei.
    • Der URL-Pfad relativ zum Stamm der Blazor WebAssembly App.
    • Der Name der Erweiterung, der die Dateien gruppiert, die von einer bestimmten Erweiterung erstellt wurden.

Nachdem Sie die oben genannten Ziele erreicht haben, wird die MSBuild-Aufgabe zum Anpassen der Blazor Veröffentlichungsausgabe erstellt. Blazor kümmert sich um das Sammeln der Erweiterungen und stellt sicher, bin\Release\net6.0\publishdass die Erweiterungen an den richtigen Speicherort im Ausgabeordner "Veröffentlichen" kopiert werden (z. B. ). Die gleichen Optimierungen (z. B. Komprimierung) werden auf die JavaScript-, Wasm- und DLL-Dateien angewendet, wie Blazor sie für andere Dateien gelten.

Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks/BundleBlazorAssets.cs:

using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks
{
    public class BundleBlazorAssets : Task
    {
        [Required]
        public ITaskItem[]? PublishBlazorBootStaticWebAsset { get; set; }

        [Required]
        public string? BundlePath { get; set; }

        [Output]
        public ITaskItem[]? Extension { get; set; }

        public override bool Execute()
        {
            var bundle = new MultipartFormDataContent(
                "--0a7e8441d64b4bf89086b85e59523b7d");

            foreach (var asset in PublishBlazorBootStaticWebAsset)
            {
                var name = Path.GetFileName(asset.GetMetadata("RelativePath"));
                var fileContents = File.OpenRead(asset.ItemSpec);
                var content = new StreamContent(fileContents);
                var disposition = new ContentDispositionHeaderValue("form-data");
                disposition.Name = name;
                disposition.FileName = name;
                content.Headers.ContentDisposition = disposition;
                var contentType = Path.GetExtension(name) switch
                {
                    ".js" => "text/javascript",
                    ".wasm" => "application/wasm",
                    _ => "application/octet-stream"
                };
                content.Headers.ContentType = 
                    MediaTypeHeaderValue.Parse(contentType);
                bundle.Add(content);
            }

            using (var output = File.Open(BundlePath, FileMode.OpenOrCreate))
            {
                output.SetLength(0);
                bundle.CopyToAsync(output).ConfigureAwait(false).GetAwaiter()
                    .GetResult();
                output.Flush(true);
            }

            var bundleItem = new TaskItem(BundlePath);
            bundleItem.SetMetadata("RelativePath", "app.bundle");
            bundleItem.SetMetadata("ExtensionName", "multipart");

            Extension = new ITaskItem[] { bundleItem };

            return true;
        }
    }
}

Erstellen eines NuGet-Pakets zum automatischen Transformieren der Veröffentlichungsausgabe

Generieren Sie ein NuGet-Paket mit MSBuild-Zielen, die automatisch eingeschlossen werden, wenn auf das Paket verwiesen wird:

  • Erstellen Sie ein neuesRazor RCL-Projekt (Class Library).
  • Erstellen Sie eine Zieldatei gemäß den NuGet-Konventionen, um das Paket automatisch in nutzende Projekte zu importieren. Erstellen Sie build\net6.0\{PACKAGE ID}.targetsz. B. , wobei {PACKAGE ID} die Paketkennung des Pakets ist.
  • Erfassen Sie die Ausgabe aus der Klassenbibliothek, die die MSBuild-Aufgabe enthält, und vergewissern Sie sich, dass die Ausgabe am richtigen Speicherort gepackt ist.
  • Fügen Sie den erforderlichen MSBuild-Code hinzu, der an die Blazor Pipeline angefügt werden soll, und rufen Sie die MSBuild-Aufgabe auf, um das Paket zu generieren.

Der in diesem Abschnitt beschriebene Ansatz verwendet das Paket nur zum Übermitteln von Zielen und Inhalten, was sich von den meisten Paketen unterscheidet, bei denen das Paket eine Bibliotheks-DLL enthält.

Warnung

Das in diesem Abschnitt beschriebene Beispielpaket veranschaulicht, wie der Blazor Veröffentlichungsprozess angepasst wird. Das NuGet-Beispielpaket dient nur zur Verwendung als lokale Demonstration. Die Verwendung dieses Pakets in der Produktion wird nicht unterstützt.

Hinweis

Das NuGet-Paket für die Beispiele in diesem Artikel ist nach dem von Microsoft bereitgestellten Paket benannt. Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle Anleitungen zum Benennen und Erstellen eines eigenen NuGet-Pakets finden Sie in den folgenden NuGet-Artikeln:

Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.csproj:

<Project Sdk="Microsoft.NET.Sdk.Razor">

  <PropertyGroup>
    <NoWarn>NU5100</NoWarn>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <Description>
      Sample demonstration package showing how to customize the Blazor publish 
      process. Using this package in production is not supported!
    </Description>
    <IsPackable>true</IsPackable>
    <IsShipping>true</IsShipping>
    <IncludeBuildOutput>false</IncludeBuildOutput>
  </PropertyGroup>

  <ItemGroup>
    <None Update="build\**" 
          Pack="true" 
          PackagePath="%(Identity)" />
    <Content Include="_._" 
             Pack="true" 
             PackagePath="lib\net6.0\_._" />
  </ItemGroup>

  <Target Name="GetTasksOutputDlls" 
          BeforeTargets="CoreCompile">
    <MSBuild Projects="..\Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks\Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks.csproj" 
             Targets="Publish;PublishItemsOutputGroup" 
             Properties="Configuration=Release">
      <Output TaskParameter="TargetOutputs" 
              ItemName="_TasksProjectOutputs" />
    </MSBuild>
    <ItemGroup>
      <Content Include="@(_TasksProjectOutputs)" 
               Condition="'%(_TasksProjectOutputs.Extension)' == '.dll'" 
               Pack="true" 
               PackagePath="tasks\%(_TasksProjectOutputs.TargetPath)" 
               KeepMetadata="Pack;PackagePath" />
    </ItemGroup>
  </Target>

</Project>

Hinweis

Die <NoWarn>NU5100</NoWarn> Eigenschaft im vorherigen Beispiel unterdrückt die Warnung zu den im Ordner abgelegten tasks Assemblys. Weitere Informationen finden Sie unter NuGet-Warnung NU5100.

Fügen Sie eine .targets Datei hinzu, um die MSBuild-Aufgabe mit der Buildpipeline zu verknüpfen. In dieser Datei werden die folgenden Ziele erreicht:

  • Importieren Sie die Aufgabe in den Buildprozess. Beachten Sie, dass der Pfad zur DLL relativ zum endgültigen Speicherort der Datei im Paket ist.
  • Die ComputeBlazorExtensionsDependsOn Eigenschaft fügt das benutzerdefinierte Ziel an die Blazor WebAssembly Pipeline an.
  • Erfassen Sie die Extension Eigenschaft in der Aufgabenausgabe, und fügen Sie sie hinzu, BlazorPublishExtension um über die Erweiterung zu informieren Blazor . Durch Aufrufen der Aufgabe im Ziel wird das Bundle erstellt. Die Liste der veröffentlichten Dateien wird von der Blazor WebAssembly Pipeline in der PublishBlazorBootStaticWebAsset Elementgruppe bereitgestellt. Der Bundle-Pfad wird mit dem IntermediateOutputPath (in der Regel innerhalb des obj Ordners) definiert. Letztendlich wird das Bundle automatisch an den richtigen Speicherort im Ausgabeordner für die Veröffentlichung kopiert (z. B bin\Release\net6.0\publish. ).

Wenn auf das Paket verwiesen wird, wird während der Veröffentlichung ein Bundle der Blazor Dateien generiert.

Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/build/net6.0/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.targets:

<Project>
  <UsingTask 
    TaskName="Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks.BundleBlazorAssets" 
    AssemblyFile="$(MSBuildThisProjectFileDirectory)..\..\tasks\Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.Tasks.dll" />

  <PropertyGroup>
    <ComputeBlazorExtensionsDependsOn>
      $(ComputeBlazorExtensionsDependsOn);_BundleBlazorDlls
    </ComputeBlazorExtensionsDependsOn>
  </PropertyGroup>

  <Target Name="_BundleBlazorDlls">
    <BundleBlazorAssets
      PublishBlazorBootStaticWebAsset="@(PublishBlazorBootStaticWebAsset)"
      BundlePath="$(IntermediateOutputPath)bundle.multipart">
      <Output TaskParameter="Extension" 
              ItemName="BlazorPublishExtension"/>
    </BundleBlazorAssets>
  </Target>

</Project>

Automatisches Bootstrapping Blazor aus dem Bundle

Das NuGet-Paket nutzt JavaScript-Initialisierer (JS), um eine Blazor WebAssembly App automatisch aus dem Bundle zu bootstrappen, anstatt einzelne DLL-Dateien zu verwenden. JS Initialisierer werden verwendet, um den BlazorBoot-Resource-Loader zu ändern und das Bundle zu verwenden.

Um einen JS Initialisierer zu erstellen, fügen Sie dem JS Ordner des Paketprojekts eine {NAME}.lib.module.js Datei mit dem Namen wwwroot hinzu, wobei der {NAME} Platzhalter der Paketbezeichner ist. Die Datei für das Microsoft-Paket heißt Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.jsz. B. . Die exportierten Funktionen beforeWebAssemblyStart und afterWebAssemblyStarted verarbeiten das Laden.

Die JS Initialisierer:

Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/wwwroot/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.js:

const resources = new Map();

export async function beforeWebAssemblyStart(options, extensions) {
  if (!extensions || !extensions.multipart) {
    return;
  }

  try {
    const integrity = extensions.multipart['app.bundle'];
    const bundleResponse = 
      await fetch('app.bundle', { integrity: integrity, cache: 'no-cache' });
    const bundleFromData = await bundleResponse.formData();
    for (let value of bundleFromData.values()) {
      resources.set(value, URL.createObjectURL(value));
    }
    options.loadBootResource = function (type, name, defaultUri, integrity) {
      return resources.get(name) ?? null;
    }
  } catch (error) {
    console.log(error);
  }
}

export async function afterWebAssemblyStarted(blazor) {
  for (const [_, url] of resources) {
    URL.revokeObjectURL(url);
  }
}

Um einen JS Initialisierer zu erstellen, fügen Sie dem JS Ordner des Paketprojekts eine {NAME}.lib.module.js Datei mit dem Namen wwwroot hinzu, wobei der {NAME} Platzhalter der Paketbezeichner ist. Die Datei für das Microsoft-Paket heißt Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.jsz. B. . Die exportierten Funktionen beforeStart und afterStarted verarbeiten das Laden.

Die JS Initialisierer:

Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle/wwwroot/Microsoft.AspNetCore.Components.WebAssembly.MultipartBundle.lib.module.js:

const resources = new Map();

export async function beforeStart(options, extensions) {
  if (!extensions || !extensions.multipart) {
    return;
  }

  try {
    const integrity = extensions.multipart['app.bundle'];
    const bundleResponse = 
      await fetch('app.bundle', { integrity: integrity, cache: 'no-cache' });
    const bundleFromData = await bundleResponse.formData();
    for (let value of bundleFromData.values()) {
      resources.set(value, URL.createObjectURL(value));
    }
    options.loadBootResource = function (type, name, defaultUri, integrity) {
      return resources.get(name) ?? null;
    }
  } catch (error) {
    console.log(error);
  }
}

export async function afterStarted(blazor) {
  for (const [_, url] of resources) {
    URL.revokeObjectURL(url);
  }
}

Bereitstellen des Pakets über die Hostserver-App

Aufgrund von Sicherheitseinschränkungen stellt ASP.NET Core die app.bundle Datei nicht bereit. Ein Hilfsprogramm für die Anforderungsverarbeitung ist erforderlich, um die Datei bereitzustellen, wenn sie von Clients angefordert wird.

Hinweis

Da die gleichen Optimierungen transparent auf die Veröffentlichungserweiterungen angewendet werden, die auf die Dateien der App angewendet werden, werden die und app.bundle.gz die komprimierten Objektdateien bei der app.bundle.br Veröffentlichung automatisch erstellt.

Platzieren Sie C#-Code im Program.csServer Projekt unmittelbar vor der Zeile, die die Fallback-Datei auf index.html (app.MapFallbackToFile("index.html");) setzt, app.bundleum auf eine Anforderung für die Bundle-Datei zu antworten (z. B. ):

app.MapGet("app.bundle", (HttpContext context) =>
{
    string? contentEncoding = null;
    var contentType = 
        "multipart/form-data; boundary=\"--0a7e8441d64b4bf89086b85e59523b7d\"";
    var fileName = "app.bundle";

    var acceptEncodings = context.Request.Headers.AcceptEncoding;

    if (Microsoft.Net.Http.Headers.StringWithQualityHeaderValue
        .StringWithQualityHeaderValue
        .TryParseList(acceptEncodings, out var encodings))
    {
        if (encodings.Any(e => e.Value == "br"))
        {
            contentEncoding = "br";
            fileName += ".br";
        }
        else if (encodings.Any(e => e.Value == "gzip"))
        {
            contentEncoding = "gzip";
            fileName += ".gz";
        }
    }

    if (contentEncoding != null)
    {
        context.Response.Headers.ContentEncoding = contentEncoding;
    }

    return Results.File(
        app.Environment.WebRootFileProvider.GetFileInfo(fileName)
            .CreateReadStream(), contentType);
});

Der Inhaltstyp entspricht dem Typ, der zuvor in der Buildaufgabe definiert wurde. Der Endpunkt prüft, ob die vom Browser akzeptierten Inhaltskodierungen vorhanden sind, und stellt die optimale Datei Brotli (.br) oder Gzip (.gz) bereit.