Přehled jednostrákových aplikací (SPA) v ASP.NET Core

Poznámka:

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Důležité

Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.

Aktuální verzi najdete ve verzi .NET 8 tohoto článku.

Visual Studio poskytuje šablony projektů pro vytváření jednostrákových aplikací (SPA) založených na architekturách JavaScriptu, jako jsou Angular, React a Vue , které mají back-end ASP.NET Core. Tyto šablony:

  • Vytvořte řešení sady Visual Studio s front-endovým projektem a back-endovým projektem.
  • Pro front-end použijte typ projektu sady Visual Studio pro JavaScript a TypeScript (.esproj).
  • Pro back-end použijte projekt ASP.NET Core.

Projekty vytvořené pomocí šablon sady Visual Studio je možné spustit z příkazového řádku ve Windows, Linuxu a macOS. Pokud chcete aplikaci spustit, použijte dotnet run --launch-profile https ji ke spuštění serverového projektu. Spuštění serverového projektu automaticky spustí front-endový vývojový server JavaScriptu. V https současné době se vyžaduje spouštěcí profil.

Kurzy k sadě Visual Studio

Pokud chcete začít, postupujte podle některého z kurzů v dokumentaci k sadě Visual Studio:

Další informace najdete v tématu JavaScript a TypeScript v sadě Visual Studio.

šablony ASP.NET Core SPA

Visual Studio obsahuje šablony pro vytváření aplikací ASP.NET Core pomocí front-endu JavaScriptu nebo TypeScriptu. Tyto šablony jsou k dispozici v sadě Visual Studio 2022 verze 17.8 nebo novější s nainstalovanou úlohou vývoje pro ASP.NET a web .

Šablony sady Visual Studio pro vytváření aplikací ASP.NET Core s front-endem JavaScriptu nebo TypeScriptu nabízejí následující výhody:

  • Vyčištění oddělení projektů pro front-end a back-end
  • Mějte přehled o nejnovějších verzích front-endové architektury.
  • Integrace s nejnovějšími nástroji příkazového řádku front-endové architektury, jako je Vite.
  • Šablony pro JavaScript i TypeScript (pouze TypeScript pro Angular).
  • Bohaté prostředí pro úpravy kódu v JavaScriptu a TypeScriptu
  • Integrujte nástroje sestavení JavaScriptu s sestavením .NET.
  • npm dependency management UI.
  • Kompatibilní s laděním a spuštěním editoru Visual Studio Code.
  • Spouštění testů částí front-endu v Průzkumníku testů pomocí testovacích architektur JavaScriptu

Starší verze šablon ASP.NET Core SPA

Starší verze sady .NET SDK obsahovaly starší šablony pro vytváření aplikací SPA pomocí ASP.NET Core. Dokumentaci k těmto starším šablonám najdete v článcích o ASP.NET Core 7.0 přehledu spa a článcích o Angular a Reactu .

Architektura jednostrákových šablon aplikací

Šablony jednostránkové aplikace (SPA) pro Angular a React nabízejí možnost vyvíjet aplikace Angular a React hostované na back-endovém serveru .NET.

Při publikování se soubory aplikace Angular a React zkopírují do wwwroot složky a obsluhují se prostřednictvím middlewaru statických souborů.

Místo vrácení protokolu HTTP 404 (Nenalezena) zpracovává náhradní trasa neznámé požadavky na back-end a slouží index.html pro spa.

Během vývoje je aplikace nakonfigurovaná tak, aby používala front-endový proxy server. React a Angular používají stejný front-endový proxy server.

Po spuštění index.html aplikace se stránka otevře v prohlížeči. Speciální middleware, který je povolený pouze ve vývoji:

  • Zachytí příchozí požadavky.
  • Zkontroluje, jestli je proxy server spuštěný.
  • Přesměruje se na adresu URL proxy serveru, pokud je spuštěná nebo spustí novou instanci proxy serveru.
  • Vrátí stránku do prohlížeče, který se automaticky aktualizuje každých několik sekund, dokud se proxy server nesměruje a prohlížeč se přesměruje.

Diagram proxy serveru prohlížeče

Hlavním přínosem jsou šablony ASP.NET Core SPA:

  • Spustí proxy server, pokud ještě není spuštěný.
  • Nastavení HTTPS
  • Konfigurace některých požadavků na proxy server back-endu ASP.NET Core.

Když prohlížeč odešle požadavek na koncový bod back-endu, například /weatherforecast v šablonách. Proxy služby SPA přijme požadavek a transparentně ho odešle zpět na server. Server odpoví a proxy služby SPA odešle požadavek zpět do prohlížeče:

Diagram proxy serveru

Publikované jednostráňové aplikace

Po publikování aplikace se spa stane kolekcí souborů ve wwwroot složce.

Pro obsluhu aplikace není nutná žádná komponenta modulu runtime:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();


app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");

app.MapFallbackToFile("index.html");

app.Run();

V předchozím vygenerovaném Program.cs souboru šablony:

  • app.UseStaticFiles umožňuje obsluhovat soubory.
  • app.MapFallbackToFile("index.html") umožňuje obsluhovat výchozí dokument pro všechny neznámé požadavky, které server obdrží.

Když je aplikace publikovaná s publikováním dotnet, následující úlohy v csproj souboru zajistí spuštění npm restore a spuštění příslušného skriptu npm ke generování produkčních artefaktů:

  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
    <!-- Ensure Node.js is installed -->
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)build\**" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>wwwroot\%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
        <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>
</Project>

Vývoj jednostrákových aplikací

Soubor projektu definuje několik vlastností, které řídí chování aplikace během vývoje:

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

  <PropertyGroup>
    <TargetFramework>net7.0</TargetFramework>
    <Nullable>enable</Nullable>
    <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
    <TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
    <IsPackable>false</IsPackable>
    <SpaRoot>ClientApp\</SpaRoot>
    <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
    <SpaProxyServerUrl>https://localhost:44414</SpaProxyServerUrl>
    <SpaProxyLaunchCommand>npm start</SpaProxyLaunchCommand>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.SpaProxy" Version="7.0.1" />
  </ItemGroup>

  <ItemGroup>
    <!-- Don't publish the SPA source files, but do show them in the project files list -->
    <Content Remove="$(SpaRoot)**" />
    <None Remove="$(SpaRoot)**" />
    <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
  </ItemGroup>

  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
    <!-- Ensure Node.js is installed -->
    <Exec Command="node --version" ContinueOnError="true">
      <Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
    </Exec>
    <Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
    <Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
  </Target>

  <Target Name="PublishRunWebpack" AfterTargets="ComputeFilesToPublish">
    <!-- As part of publishing, ensure the JS resources are freshly built in production mode -->
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="npm run build" />

    <!-- Include the newly-built files in the publish output -->
    <ItemGroup>
      <DistFiles Include="$(SpaRoot)build\**" />
      <ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
        <RelativePath>wwwroot\%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
        <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
        <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
      </ResolvedFileToPublish>
    </ItemGroup>
  </Target>
</Project>
  • SpaProxyServerUrl: Určuje adresu URL, kde server očekává, že bude spuštěn proxy spa. Toto je adresa URL:
    • Server odešle příkaz ping po spuštění proxy serveru, aby věděl, jestli je připravený.
    • Tam, kde přesměruje prohlížeč po úspěšné odpovědi.
  • SpaProxyLaunchCommand: Příkaz, který server používá ke spuštění proxy spa, když zjistí, že proxy server není spuštěný.

Microsoft.AspNetCore.SpaProxy Balíček zodpovídá za předchozí logiku, která rozpozná proxy server a přesměruje prohlížeč.

Hostitelské spouštěcí sestavení definované v Properties/launchSettings.json slouží k automatickému přidání požadovaných komponent během vývoje, aby bylo možné zjistit, jestli je proxy server spuštěný, a spustit ho jinak:

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:51783",
      "sslPort": 44329
    }
  },
  "profiles": {
    "MyReact": {
      "commandName": "Project",
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7145;http://localhost:5273",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
      }
    }
  }
}

Nastavení klientské aplikace

Toto nastavení je specifické pro front-endovou architekturu, které aplikace používá, ale mnoho aspektů konfigurace je podobné.

Nastavení Angular

Vygenerovaný ClientApp/package.json soubor šablony:

{
  "name": "myangular",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "prestart": "node aspnetcore-https",
    "start": "run-script-os",
    "start:windows": "ng serve --port 44483 --ssl --ssl-cert \"%APPDATA%\\ASP.NET\\https\\%npm_package_name%.pem\" --ssl-key \"%APPDATA%\\ASP.NET\\https\\%npm_package_name%.key\"",
    "start:default": "ng serve --port 44483 --ssl --ssl-cert \"$HOME/.aspnet/https/${npm_package_name}.pem\" --ssl-key \"$HOME/.aspnet/https/${npm_package_name}.key\"",
    "build": "ng build",
    "build:ssr": "ng run MyAngular:server:dev",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^14.1.3",
    "@angular/common": "^14.1.3",
    "@angular/compiler": "^14.1.3",
    "@angular/core": "^14.1.3",
    "@angular/forms": "^14.1.3",
    "@angular/platform-browser": "^14.1.3",
    "@angular/platform-browser-dynamic": "^14.1.3",
    "@angular/platform-server": "^14.1.3",
    "@angular/router": "^14.1.3",
    "bootstrap": "^5.2.0",
    "jquery": "^3.6.0",
    "oidc-client": "^1.11.5",
    "popper.js": "^1.16.0",
    "run-script-os": "^1.1.6",
    "rxjs": "~7.5.6",
    "tslib": "^2.4.0",
    "zone.js": "~0.11.8"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^14.1.3",
    "@angular/cli": "^14.1.3",
    "@angular/compiler-cli": "^14.1.3",
    "@types/jasmine": "~4.3.0",
    "@types/jasminewd2": "~2.0.10",
    "@types/node": "^18.7.11",
    "jasmine-core": "~4.3.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.1.1",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "^2.0.0",
    "typescript": "~4.7.4"
  },
  "overrides": {
    "autoprefixer": "10.4.5"
  },
  "optionalDependencies": {}
}
  • Obsahuje skripty, které spouští angulární vývojový server:

  • Skript prestart vyvolá ClientApp/aspnetcore-https.js, který je zodpovědný za zajištění dostupnosti certifikátu HTTPS vývojového serveru pro proxy server SPA.

  • start:defaultAstart:windows:

    • Spusťte vývojový server Angular prostřednictvím ng serve.
    • Zadejte port, možnosti použití PROTOKOLU HTTPS a cestu k certifikátu a přidruženému klíči. Zadané číslo portu odpovídá číslu portu zadanému .csproj v souboru.

Vygenerovaný ClientApp/angular.json soubor šablony obsahuje:

  • Příkaz serve .

  • Prvek proxyconfig v development konfiguraci, který označuje, že proxy.conf.js se má použít ke konfiguraci front-endového proxy serveru, jak je znázorněno v následujícím zvýrazněné zapnuté funkci JS:

    {
      "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
      "version": 1,
      "newProjectRoot": "projects",
      "projects": {
        "MyAngular": {
          "projectType": "application",
          "schematics": {
            "@schematics/angular:application": {
              "strict": true
            }
          },
          "root": "",
          "sourceRoot": "src",
          "prefix": "app",
          "architect": {
            "build": {
              "builder": "@angular-devkit/build-angular:browser",
              "options": {
                "progress": false,
                "outputPath": "dist",
                "index": "src/index.html",
                "main": "src/main.ts",
                "polyfills": "src/polyfills.ts",
                "tsConfig": "tsconfig.app.json",
                "allowedCommonJsDependencies": [
                  "oidc-client"
                ],
                "assets": [
                  "src/assets"
                ],
                "styles": [
                  "node_modules/bootstrap/dist/css/bootstrap.min.css",
                  "src/styles.css"
                ],
                "scripts": []
              },
              "configurations": {
                "production": {
                  "budgets": [
                    {
                      "type": "initial",
                      "maximumWarning": "500kb",
                      "maximumError": "1mb"
                    },
                    {
                      "type": "anyComponentStyle",
                      "maximumWarning": "2kb",
                      "maximumError": "4kb"
                    }
                  ],
                  "fileReplacements": [
                    {
                      "replace": "src/environments/environment.ts",
                      "with": "src/environments/environment.prod.ts"
                    }
                  ],
                  "outputHashing": "all"
                },
                "development": {
                  "buildOptimizer": false,
                  "optimization": false,
                  "vendorChunk": true,
                  "extractLicenses": false,
                  "sourceMap": true,
                  "namedChunks": true
                }
              },
              "defaultConfiguration": "production"
            },
            "serve": {
              "builder": "@angular-devkit/build-angular:dev-server",
              "configurations": {
                "production": {
                  "browserTarget": "MyAngular:build:production"
                },
                "development": {
                  "browserTarget": "MyAngular:build:development",
                  "proxyConfig": "proxy.conf.js"
                }
              },
              "defaultConfiguration": "development"
            },
            "extract-i18n": {
              "builder": "@angular-devkit/build-angular:extract-i18n",
              "options": {
                "browserTarget": "MyAngular:build"
              }
            },
            "test": {
              "builder": "@angular-devkit/build-angular:karma",
              "options": {
                "main": "src/test.ts",
                "polyfills": "src/polyfills.ts",
                "tsConfig": "tsconfig.spec.json",
                "karmaConfig": "karma.conf.js",
                "assets": [
                  "src/assets"
                ],
                "styles": [
                  "src/styles.css"
                ],
                "scripts": []
              }
            },
            "server": {
              "builder": "@angular-devkit/build-angular:server",
              "options": {
                "outputPath": "dist-server",
                "main": "src/main.ts",
                "tsConfig": "tsconfig.server.json"
              },
              "configurations": {
                "dev": {
                  "optimization": true,
                  "outputHashing": "all",
                  "sourceMap": false,
                  "namedChunks": false,
                  "extractLicenses": true,
                  "vendorChunk": true
                },
                "production": {
                  "optimization": true,
                  "outputHashing": "all",
                  "sourceMap": false,
                  "namedChunks": false,
                  "extractLicenses": true,
                  "vendorChunk": false
                }
              }
            }
          }
        }
      },
      "defaultProject": "MyAngular"
    }
    

ClientApp/proxy.conf.js definuje trasy, které je potřeba směrovat zpět na back-end serveru. Obecná sada možností je definována v http-proxy-middleware pro react a angular, protože oba používají stejný proxy server.

Následující zvýrazněný kód z ClientApp/proxy.conf.js použití logiky založené na proměnných prostředí nastavených během vývoje k určení portu, na kterém je back-end spuštěný:

const { env } = require('process');

const target = env.ASPNETCORE_HTTPS_PORTS ? `https://localhost:${env.ASPNETCORE_HTTPS_PORTS}` :
  env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:51951';

const PROXY_CONFIG = [
  {
    context: [
      "/weatherforecast",
   ],
    target: target,
    secure: false,
    headers: {
      Connection: 'Keep-Alive'
    }
  }
]

module.exports = PROXY_CONFIG;

Nastavení Reactu

  • Část package.json Skripty obsahuje následující skripty, které spustí aplikaci React během vývoje, jak je znázorněno v následujícím zvýrazněném kódu:

    {
      "name": "myreact",
      "version": "0.1.0",
      "private": true,
      "dependencies": {
        "bootstrap": "^5.2.0",
        "http-proxy-middleware": "^2.0.6",
        "jquery": "^3.6.0",
        "merge": "^2.1.1",
        "oidc-client": "^1.11.5",
        "react": "^18.2.0",
        "react-dom": "^18.2.0",
        "react-router-bootstrap": "^0.26.2",
        "react-router-dom": "^6.3.0",
        "react-scripts": "^5.0.1",
        "reactstrap": "^9.1.3",
        "rimraf": "^3.0.2",
        "web-vitals": "^2.1.4",
        "workbox-background-sync": "^6.5.4",
        "workbox-broadcast-update": "^6.5.4",
        "workbox-cacheable-response": "^6.5.4",
        "workbox-core": "^6.5.4",
        "workbox-expiration": "^6.5.4",
        "workbox-google-analytics": "^6.5.4",
        "workbox-navigation-preload": "^6.5.4",
        "workbox-precaching": "^6.5.4",
        "workbox-range-requests": "^6.5.4",
        "workbox-routing": "^6.5.4",
        "workbox-strategies": "^6.5.4",
        "workbox-streams": "^6.5.4"
      },
      "devDependencies": {
        "ajv": "^8.11.0",
        "cross-env": "^7.0.3",
        "eslint": "^8.22.0",
        "eslint-config-react-app": "^7.0.1",
        "eslint-plugin-flowtype": "^8.0.3",
        "eslint-plugin-import": "^2.26.0",
        "eslint-plugin-jsx-a11y": "^6.6.1",
        "eslint-plugin-react": "^7.30.1",
        "nan": "^2.16.0",
        "typescript": "^4.7.4"
      },
      "overrides": {
        "autoprefixer": "10.4.5"
      },
      "resolutions": {
        "css-what": "^5.0.1",
        "nth-check": "^3.0.1"
      },
      "scripts": {
        "prestart": "node aspnetcore-https && node aspnetcore-react",
        "start": "rimraf ./build && react-scripts start",
        "build": "react-scripts build",
        "test": "cross-env CI=true react-scripts test --env=jsdom",
        "eject": "react-scripts eject",
        "lint": "eslint ./src/"
      },
      "eslintConfig": {
        "extends": [
          "react-app"
        ]
      },
      "browserslist": {
        "production": [
          ">0.2%",
          "not dead",
          "not op_mini all"
        ],
        "development": [
          "last 1 chrome version",
          "last 1 firefox version",
          "last 1 safari version"
        ]
      }
    }
    
  • Skript prestart vyvolá:

    • aspnetcore-https.js, který zodpovídá za zajištění dostupnosti certifikátu HTTPS vývojového serveru pro proxy server SPA.
    • aspnetcore-react.js Vyvolá nastavení příslušného .env.development.local souboru pro použití místního vývojového certifikátu HTTPS. aspnetcore-react.js nakonfiguruje místní vývojový certifikát HTTPS přidáním SSL_CRT_FILE=<certificate-path> a SSL_KEY_FILE=<key-path> do souboru.
  • Soubor .env.development definuje port pro vývojový server a určuje PROTOKOL HTTPS.

Nakonfiguruje src/setupProxy.js proxy spa tak, aby předával požadavky do back-endu. Obecná sada možností je definována v http-proxy-middleware.

Následující zvýrazněný kód používá ClientApp/src/setupProxy.js logiku založenou na proměnných prostředí nastavených během vývoje k určení portu, na kterém je back-end spuštěný:

const { createProxyMiddleware } = require('http-proxy-middleware');
const { env } = require('process');

const target = env.ASPNETCORE_HTTPS_PORTS ? `https://localhost:${env.ASPNETCORE_HTTPS_PORTS}` :
  env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:51783';

const context = [
  "/weatherforecast",
];

const onError = (err, req, resp, target) => {
    console.error(`${err.message}`);
}

module.exports = function (app) {
  const appProxy = createProxyMiddleware(context, {
    target: target,
    // Handle errors to prevent the proxy middleware from crashing when
    // the ASP NET Core webserver is unavailable
    onError: onError,
    secure: false,
    // Uncomment this line to add support for proxying websockets
    //ws: true, 
    headers: {
      Connection: 'Keep-Alive'
    }
  });

  app.use(appProxy);
};

Podporovaná verze architektury SPA v šablonách ASP.NET Core SPA

Šablony projektů SPA, které se dodávají s každou verzí ASP.NET Core, odkazují na nejnovější verzi příslušné architektury SPA.

Architektury SPA mají obvykle kratší cyklus vydávání než .NET. Vzhledem ke dvěma různým cyklům vydání se podporovaná verze architektury SPA a .NET můžou dostat ze synchronizace: hlavní verze architektury SPA, na které závisí hlavní verze .NET, může dojít k výpadku podpory, zatímco verze .NET, se kterou je architektura SPA dodávána, je stále podporovaná.

Šablony ASP.NET Core SPA je možné aktualizovat ve vydané verzi opravy na novou verzi architektury SPA, aby byly šablony v podporovaném a bezpečném stavu.

Další materiály