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.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v tématu .NET a .NET Core Zásady podpory. 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:
- Vytvoření aplikace ASP.NET Core pomocí Angular
- Vytvoření aplikace ASP.NET Core pomocí Reactu
- Vytvoření aplikace ASP.NET Core pomocí Vue
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.
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:
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:default
Astart: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.
- Spusťte vývojový server Angular prostřednictvím
Vygenerovaný ClientApp/angular.json
soubor šablony obsahuje:
Příkaz
serve
.Prvek
proxyconfig
vdevelopment
konfiguraci, který označuje, žeproxy.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ímSSL_CRT_FILE=<certificate-path>
aSSL_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.