Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Z tego artykułu dowiesz się, jak używać aplikacji Node.js i Node Package Manager (npm
) w projekcie .NET.NET Aspire. Przykładowa aplikacja w tym artykule demonstruje Angular, Reacti Vue doświadczenia klienta. Następujące interfejsy API .NET.NET Aspire istnieją, aby obsługiwać te scenariusze — i są one częścią pakietu NuGet Aspire.Hosting.NodeJS.
Różnica między tymi dwoma interfejsami API polega na tym, że pierwszy służy do hostowania aplikacji Node.js, natomiast drugi jest używany do hostowania aplikacji wykonywanych z sekcji pliku scripts
oraz odpowiadającego polecenia npm run <script-name>
.
Napiwek
Przykładowy kod źródłowy tego artykułu jest dostępny w witrynie GitHubi są dostępne szczegółowe informacje na stronie przykłady kodu : .NET Aspire z Angular, React i Vue.
Ważny
Chociaż ten artykuł koncentruje się na frontend'owych elementach aplikacji Single-Page (SPA), na stronie z przykładami kodu Node.js, dostępny jest dodatkowy przykład .NET Aspire, który pokazuje, jak używać Node.js jako aplikacji serwerowej z express.
Warunki wstępne
Aby pracować z .NET.NET Aspire, musisz mieć zainstalowane lokalnie następujące elementy:
- .NET 8.0 lub .NET 9.0
- Środowisko uruchomieniowe kontenera zgodne ze standardem OCI, takie jak:
- Docker Desktop lub Podman. Aby uzyskać więcej informacji, zobacz Czas działania kontenera.
- Zintegrowane środowisko deweloperskie (IDE) lub edytor kodu, takie jak:
- Visual Studio 2022 w wersji 17.9 lub nowszej (opcjonalnie)
-
Visual Studio Code (opcjonalnie)
- C# Dev Kit: Rozszerzenie (opcjonalnie)
- JetBrains Rider z wtyczką .NET.NET Aspire (opcjonalnie)
Aby uzyskać więcej informacji, zobacz .NET.NET Aspire setup and toolingi .NET.NET Aspire SDK.
Ponadto należy zainstalować Node.js na maszynie. Przykładowa aplikacja w tym artykule została skompilowana przy użyciu Node.js w wersji 20.12.2 i narzędzia npm w wersji 10.5.1. Aby zweryfikować wersje Node.js i npm, uruchom następujące polecenia:
node --version
npm --version
Aby pobrać Node.js (w tym npm
), zobacz stronę pobierania Node.js.
Klonowanie przykładowego kodu źródłowego
Aby sklonować przykładowy kod źródłowy z GitHub, uruchom następujące polecenie:
git clone https://github.com/dotnet/aspire-samples.git
Po sklonowaniu repozytorium przejdź do folderu samples/AspireWithJavaScript:
cd samples/AspireWithJavaScript
Z tego katalogu znajduje się sześć opisanych poniżej katalogów podrzędnych:
- AspireJavaScript.Angular: aplikacja Angular, która wykorzystuje API prognoz pogody i wyświetla dane w tabeli.
- AspireJavaScript.AppHost: projekt .NET.NET Aspire, który organizuje inne aplikacje w tym przykładzie. Aby uzyskać więcej informacji, zobacz omówienie orkiestracji .NET.NET Aspire.
- AspireJavaScript.MinimalApi: interfejs API HTTP, który zwraca losowo wygenerowane dane prognozy pogody.
- AspireJavaScript.React: Aplikacja React, która korzysta z interfejsu API prognozy pogody i wyświetla dane w tabeli.
- AspireJavaScript.ServiceDefaults: domyślny udostępniony projekt dla projektów .NET.NET Aspire. Aby uzyskać więcej informacji, zobacz ustawienia domyślne usługi .NET.NET Aspire.
- AspireJavaScript.Vue: Aplikacja Vue, która korzysta z interfejsu API prognozy pogody i wyświetla dane w tabeli.
Instalowanie zależności klienta
Przykładowa aplikacja pokazuje, jak używać aplikacji klienckich JavaScript opartych na Node.js. Każda aplikacja kliencka została napisana przy użyciu polecenia szablonu npm create
lub ręcznie. W poniższej tabeli wymieniono polecenia szablonu używane do tworzenia każdej aplikacji klienckiej wraz z portem domyślnym:
Typ aplikacji | Polecenie Create template (Tworzenie szablonu) | Port domyślny |
---|---|---|
Angular | npm create @angular@latest |
4200 |
React | Nie użyto szablonu. | Port env var |
Vue | npm create vue@latest |
5173 |
Napiwek
Nie musisz uruchamiać żadnego z tych poleceń, ponieważ przykładowa aplikacja zawiera już klientów. Zamiast tego jest to punkt odniesienia, na podstawie którego stworzono klientów. Aby uzyskać więcej informacji, zobacz npm-init.
Aby uruchomić aplikację, należy najpierw zainstalować zależności dla każdego klienta. W tym celu przejdź do każdego folderu klienta i uruchom polecenia npm install
(lub alias instalacyjny npm i
).
Instalowanie zależności Angular
npm i ./AspireJavaScript.Angular/
Aby uzyskać więcej informacji na temat aplikacji Angular, zapoznaj się z klientem Angular.
Instalowanie zależności React
npm i ./AspireJavaScript.React/
Aby uzyskać więcej informacji na temat aplikacji React, zapoznaj się z klientem React.
Instalowanie zależności Vue
npm i ./AspireJavaScript.Vue/
Aby uzyskać więcej informacji na temat aplikacji Vue, zapoznaj się z klientem Vue.
Uruchamianie przykładowej aplikacji
Aby uruchomić przykładową aplikację, wywołaj polecenie dotnet run, przy użyciu hosta aplikacji orkiestratora AspireJavaScript.AppHost.csproj jako przełącznik --project
.
dotnet run --project ./AspireJavaScript.AppHost/AspireJavaScript.AppHost.csproj
Pulpit nawigacyjny .NET.NET Aspire jest uruchamiany w domyślnej przeglądarce, a każdy punkt końcowy aplikacji klienckiej jest wyświetlany w kolumnie Endpoints na stronie Resources. Na poniższej ilustracji przedstawiono pulpit nawigacyjny dla tej przykładowej aplikacji:
Punkt końcowy usługi weatherapi
prowadzi do strony Swagger UI dokumentującej interfejs API HTTP. Każda aplikacja kliencka używa tej usługi do wyświetlania danych prognozy pogody. Poszczególne aplikacje klienckie można wyświetlić, przechodząc do odpowiedniego punktu końcowego na pulpicie nawigacyjnym .NET.NET Aspire. Ich zrzuty ekranu i modyfikacje wprowadzone z punktu początkowego szablonu zostały szczegółowo opisane w poniższych sekcjach.
W tej samej sesji terminalu, która była używana do uruchamiania aplikacji, naciśnij Ctrl + C, aby zatrzymać aplikację.
Eksplorowanie hosta aplikacji
Aby dowiedzieć się, jak każdy zasób aplikacji klienckiej jest zorganizowany, zapoznaj się z projektem hosta aplikacji. Host aplikacji wymaga pakietu NuGet Aspire.Hosting.NodeJS do hostowania aplikacji Node.js.
<Project Sdk="Microsoft.NET.Sdk">
<Sdk Name="Aspire.AppHost.Sdk" Version="9.3.0" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.3.0" />
<PackageReference Include="Aspire.Hosting.NodeJs" Version="9.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AspireJavaScript.MinimalApi\AspireJavaScript.MinimalApi.csproj" />
</ItemGroup>
<Target Name="RestoreNpm" BeforeTargets="Build" Condition=" '$(DesignTimeBuild)' != 'true' ">
<ItemGroup>
<PackageJsons Include="..\*\package.json" />
</ItemGroup>
<!-- Install npm packages if node_modules is missing -->
<Message Importance="Normal" Text="Installing npm packages for %(PackageJsons.RelativeDir)" Condition="!Exists('%(PackageJsons.RootDir)%(PackageJsons.Directory)/node_modules')" />
<Exec Command="npm install" WorkingDirectory="%(PackageJsons.RootDir)%(PackageJsons.Directory)" Condition="!Exists('%(PackageJsons.RootDir)%(PackageJsons.Directory)/node_modules')" />
</Target>
</Project>
Plik projektu definiuje również cel kompilacji, który gwarantuje, że zależności npm są instalowane przed skompilowaniem hosta aplikacji. Kod hosta aplikacji (Program.cs) deklaruje zasoby aplikacji klienckiej przy użyciu interfejsu API AddNpmApp(IDistributedApplicationBuilder, String, String, String, String[]).
var builder = DistributedApplication.CreateBuilder(args);
var weatherApi = builder.AddProject<Projects.AspireJavaScript_MinimalApi>("weatherapi")
.WithExternalHttpEndpoints();
builder.AddNpmApp("angular", "../AspireJavaScript.Angular")
.WithReference(weatherApi)
.WaitFor(weatherApi)
.WithHttpEndpoint(env: "PORT")
.WithExternalHttpEndpoints()
.PublishAsDockerFile();
builder.AddNpmApp("react", "../AspireJavaScript.React")
.WithReference(weatherApi)
.WaitFor(weatherApi)
.WithEnvironment("BROWSER", "none") // Disable opening browser on npm start
.WithHttpEndpoint(env: "PORT")
.WithExternalHttpEndpoints()
.PublishAsDockerFile();
builder.AddNpmApp("vue", "../AspireJavaScript.Vue")
.WithReference(weatherApi)
.WaitFor(weatherApi)
.WithHttpEndpoint(env: "PORT")
.WithExternalHttpEndpoints()
.PublishAsDockerFile();
builder.AddNpmApp("reactvite", "../AspireJavaScript.Vite")
.WithReference(weatherApi)
.WithEnvironment("BROWSER", "none")
.WithHttpEndpoint(env: "VITE_PORT")
.WithExternalHttpEndpoints()
.PublishAsDockerFile();
builder.Build().Run();
Powyższy kod:
- Tworzy DistributedApplicationBuilder.
- Dodaje usługę „weatherapi” jako projekt na hoście aplikacji.
- Oznacza punkty końcowe HTTP jako zewnętrzne.
- W odniesieniu do usługi "weatherapi" dodaje aplikacje klienckie "angular", "react" i "vue" jako aplikacje npm.
- Każda aplikacja kliencka jest skonfigurowana do uruchamiania na innym porcie kontenera i używa zmiennej środowiskowej
PORT
w celu określenia portu. - Wszystkie aplikacje klienckie również polegają na Dockerfile do tworzenia obrazu kontenera i są skonfigurowane, aby przedstawiać się w manifeście publikowania jako kontener z interfejsu API PublishAsDockerFile.
- Każda aplikacja kliencka jest skonfigurowana do uruchamiania na innym porcie kontenera i używa zmiennej środowiskowej
Aby uzyskać więcej informacji na temat sieci pętli wewnętrznej, zobacz .NET.NET Aspire omówienie sieci pętli wewnętrznej. Aby uzyskać więcej informacji na temat wdrażania aplikacji, zobacz .NET.NET Aspire format manifestu dla konstruktorów narzędzi wdrażania.
Gdy host aplikacji organizuje uruchamianie każdej aplikacji klienckiej, używa npm run start
polecenia. To polecenie jest zdefiniowane w sekcji scripts
pliku package.json dla każdej aplikacji klienckiej. Skrypt start
służy do uruchamiania aplikacji klienckiej na określonym porcie. Każda aplikacja kliencka korzysta z serwera proxy, aby zażądać usługi "weatherapi".
Serwer proxy jest skonfigurowany w:
- Plik proxy.conf.js dla klienta Angular.
- Plik webpack.config.js dla React klienta.
- Plik vite.config .ts dla klienta Vue.
Eksplorowanie klienta Angular
Istnieje kilka kluczowych modyfikacji oryginalnego szablonu Angular. Pierwszy to dodanie pliku proxy.conf.js. Ten plik jest używany do przekierowywania żądań od klienta Angular do usługi "weatherapi".
module.exports = {
"/api": {
target:
process.env["services__weatherapi__https__0"] ||
process.env["services__weatherapi__http__0"],
secure: process.env["NODE_ENV"] !== "development",
pathRewrite: {
"^/api": "",
},
},
};
Host aplikacji .NET.NET Aspire ustawia zmienną środowiskową services__weatherapi__http__0
, która służy do rozpoznawania punktu końcowego usługi "weatherapi". Poprzednia konfiguracja proxy kieruje żądania HTTP rozpoczynające się od /api
do docelowego adresu URL określonego w zmiennej środowiskowej.
Następnie dołącz plik proxy do pliku angular.json.
Zaktualizuj element docelowy serve
, aby uwzględnić opcję proxyConfig
, odwołując się do utworzonego pliku proxy.conf.js.
Interfejs wiersza polecenia Angular będzie teraz używać konfiguracji serwera proxy podczas obsługiwania aplikacji klienckiej Angular.
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "weather:build:production"
},
"development": {
"buildTarget": "weather:build:development"
}
},
"defaultConfiguration": "development",
"options": {
"proxyConfig": "proxy.conf.js"
}
},
Trzecia aktualizacja dotyczy pliku package.json. Ten plik służy do konfigurowania klienta Angular do uruchamiania na innym porcie niż port domyślny. Jest to osiągane przy użyciu zmiennej środowiskowej PORT
, a pakiet run-script-os
npm w celu ustawienia portu.
{
"name": "angular-weather",
"version": "0.0.0",
"engines": {
"node": ">=20.12"
},
"scripts": {
"ng": "ng",
"start": "run-script-os",
"start:win32": "ng serve --port %PORT%",
"start:default": "ng serve --port $PORT",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "^19.2.1",
"@angular/common": "^19.2.1",
"@angular/compiler": "^19.2.1",
"@angular/core": "^19.2.1",
"@angular/forms": "^19.2.1",
"@angular/platform-browser": "^19.2.1",
"@angular/platform-browser-dynamic": "^19.2.1",
"@angular/router": "^19.2.1",
"rxjs": "~7.8.2",
"tslib": "^2.8.1",
"zone.js": "~0.15.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^19.2.1",
"@angular/cli": "^19.2.1",
"@angular/compiler-cli": "^19.2.1",
"@types/jasmine": "~5.1.7",
"jasmine-core": "~5.6.0",
"karma": "~6.4.4",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.1",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.8.2",
"run-script-os": "^1.1.6"
}
}
Sekcja scripts
pliku package.json służy do definiowania skryptu start
. Ten skrypt jest używany przez polecenie npm start
w celu uruchomienia aplikacji klienckiej Angular. Skrypt start
jest skonfigurowany do korzystania z pakietu run-script-os
w celu ustawienia portu, delegując do polecenia ng serve
i przekazując odpowiedni przełącznik --port
na podstawie składni właściwej dla danego systemu operacyjnego.
Aby wykonać wywołania HTTP do usługi "weatherapi", aplikacja kliencka Angular musi być skonfigurowana w taki sposób, aby zapewnić AngularHttpClient
do wstrzykiwania zależności. Jest to osiągane przy użyciu funkcji pomocnika provideHttpClient
podczas konfigurowania aplikacji w pliku app.config.ts.
import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient()
]
};
Na koniec aplikacja kliencka Angular musi wywołać punkt końcowy /api/WeatherForecast
w celu pobrania danych prognozy pogody. Istnieje kilka aktualizacji HTML, CSS i TypeScript, z których wszystkie są wykonywane w następujących plikach:
- app.component.css: Zaktualizuj arkusz CSS, aby stylizować tabelę.
- app.component.html: Zaktualizuj kod HTML, aby wyświetlić dane prognozy pogody w tabeli.
-
app.component.ts: Zaktualizuj kod TypeScript, aby wywołać punkt końcowy
/api/WeatherForecast
i wyświetlić dane w tabeli.
import { Component, Injectable } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { WeatherForecasts } from '../types/weatherForecast';
@Injectable()
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
})
export class AppComponent {
title = 'weather';
forecasts: WeatherForecasts = [];
constructor(private http: HttpClient) {
http.get<WeatherForecasts>('api/weatherforecast').subscribe({
next: result => this.forecasts = result,
error: console.error
});
}
}
Angular aplikacja działa
Aby zwizualizować aplikację klienta Angular, przejdź do punktu końcowego "angular" na pulpicie nawigacyjnym .NET Aspire. Na poniższej ilustracji przedstawiono aplikację klienta Angular:
Eksplorowanie klienta React
Aplikacja React nie została napisana przy użyciu szablonu i została napisana ręcznie. Kompletny kod źródłowy można znaleźć w repozytorium dotnet/aspire-samples. Niektóre kluczowe punkty orientacyjne znajdują się w pliku src/App.js:
import { useEffect, useState } from "react";
import "./App.css";
function App() {
const [forecasts, setForecasts] = useState([]);
const requestWeather = async () => {
const weather = await fetch("api/weatherforecast");
console.log(weather);
const weatherJson = await weather.json();
console.log(weatherJson);
setForecasts(weatherJson);
};
useEffect(() => {
requestWeather();
}, []);
return (
<div className="App">
<header className="App-header">
<h1>React Weather</h1>
<table>
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
{(
forecasts ?? [
{
date: "N/A",
temperatureC: "",
temperatureF: "",
summary: "No forecasts",
},
]
).map((w) => {
return (
<tr key={w.date}>
<td>{w.date}</td>
<td>{w.temperatureC}</td>
<td>{w.temperatureF}</td>
<td>{w.summary}</td>
</tr>
);
})}
</tbody>
</table>
</header>
</div>
);
}
export default App;
Funkcja App
jest punktem wejścia dla aplikacji klienckiej React. Używa hooków useState
i useEffect
do zarządzania stanem danych prognozy pogody. Interfejs API fetch
służy do żądania HTTP do punktu końcowego /api/WeatherForecast
. Odpowiedź jest następnie konwertowana na JSON i ustawiana jako stan danych prognozy pogody.
const HTMLWebpackPlugin = require("html-webpack-plugin");
module.exports = (env) => {
return {
entry: "./src/index.js",
devServer: {
port: env.PORT || 4001,
allowedHosts: "all",
proxy: [
{
context: ["/api"],
target:
process.env.services__weatherapi__https__0 ||
process.env.services__weatherapi__http__0,
pathRewrite: { "^/api": "" },
secure: false,
},
],
},
output: {
path: `${__dirname}/dist`,
filename: "bundle.js",
},
plugins: [
new HTMLWebpackPlugin({
template: "./src/index.html",
favicon: "./src/favicon.ico",
}),
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
["@babel/preset-react", { runtime: "automatic" }],
],
},
},
},
{
test: /\.css$/,
exclude: /node_modules/,
use: ["style-loader", "css-loader"],
},
],
},
};
};
Powyższy kod definiuje module.exports
w następujący sposób:
- Właściwość
entry
jest ustawiona na plik src/index.js. -
devServer
używa serwera proxy do przekazywania żądań do usługi "weatherapi", ustawia port według zmiennej środowiskowejPORT
i zezwala na dostęp dla wszystkich hostów. - Wynikiem
output
jest folder dist zawierający plik bundle.js. -
plugins
ustawić plik src/index.html jako szablon i uwidocznić plik favicon.ico.
Ostateczne aktualizacje dotyczą następujących plików:
- App.css: zaktualizować arkusz CSS, aby stylizować tabelę.
-
App.js: Zaktualizowanie kodu JavaScript w celu wywołania punktu końcowego
/api/WeatherForecast
i wyświetlenia danych w tabeli.
React aplikacja działa
Aby zwizualizować aplikację klienta React, przejdź do endpointu "react" w panelu .NET Aspire. Na poniższej ilustracji przedstawiono aplikację klienta React:
Eksplorowanie klienta Vue
Istnieje kilka kluczowych modyfikacji oryginalnego szablonu Vue. Podstawową aktualizacją było dodanie wywołania fetch
w pliku TheWelcome.vue, aby pobrać dane prognozy pogody z punktu końcowego /api/WeatherForecast
. Poniższy fragment kodu przedstawia wywołanie fetch
:
<script lang="ts">
interface WeatherForecast {
date: string
temperatureC: number
temperatureF: number
summary: string
};
type Forecasts = WeatherForecast[];
export default {
name: 'TheWelcome',
data() {
return {
forecasts: [],
loading: true,
error: null
}
},
mounted() {
fetch('api/weatherforecast')
.then(response => response.json())
.then(data => {
this.forecasts = data
})
.catch(error => {
this.error = error
})
.finally(() => (this.loading = false))
}
}
</script>
<template>
<table>
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
<tr v-for="forecast in (forecasts as Forecasts)">
<td>{{ forecast.date }}</td>
<td>{{ forecast.temperatureC }}</td>
<td>{{ forecast.temperatureF }}</td>
<td>{{ forecast.summary }}</td>
</tr>
</tbody>
</table>
</template>
<style>
table {
border: none;
border-collapse: collapse;
}
th {
font-size: x-large;
font-weight: bold;
border-bottom: solid .2rem hsla(160, 100%, 37%, 1);
}
th,
td {
padding: 1rem;
}
td {
text-align: center;
font-size: large;
}
tr:nth-child(even) {
background-color: var(--vt-c-black-soft);
}
</style>
Ponieważ integracja TheWelcome
jest mounted
, wywołuje punkt końcowy /api/weatherforecast
, aby pobrać dane prognozy pogody. Odpowiedź jest następnie ustawiana jako właściwość danych forecasts
. Aby ustawić port serwera, aplikacja kliencka Vue używa zmiennej środowiskowej PORT
. Można to osiągnąć przez zaktualizowanie pliku vite.config.ts:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
host: true,
port: parseInt(process.env.PORT ?? "5173"),
proxy: {
'/api': {
target: process.env.services__weatherapi__https__0 || process.env.services__weatherapi__http__0,
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, ''),
secure: false
}
}
}
})
Ponadto konfiguracja Vite określa właściwość server.proxy
do przekazywania żądań do usługi „weatherapi”. Jest to osiągane przy użyciu zmiennej środowiskowej services__weatherapi__http__0
, która jest ustawiana przez hosta aplikacji .NET.NET Aspire.
Ostateczna aktualizacja szablonu jest wprowadzana do pliku TheWelcome.vue. Ten plik wywołuje endpoint /api/WeatherForecast
w celu pobrania danych prognozy pogody i wyświetla dane w tabeli. Obejmuje ona aktualizacje CSS, HTML i TypeScript.
Vue aplikacja działa
Aby zobaczyć aplikację klienta Vue, przejdź do endpointu "vue" na pulpicie nawigacyjnym .NET Aspire. Na poniższej ilustracji przedstawiono aplikację klienta Vue:
Zagadnienia dotyczące wdrażania
Przykładowy kod źródłowy tego artykułu jest przeznaczony do uruchamiania lokalnie. Każda aplikacja kliencka jest wdrażana jako obraz kontenera. Dockerfile dla każdej aplikacji klienckiej służy do kompilowania obrazu kontenera. Każda Dockerfile jest identyczna, korzystając z kompilacji wielostopniowej do utworzenia obrazu kontenera gotowego do produkcji.
FROM node:20 as build
WORKDIR /app
COPY package.json package.json
COPY package-lock.json package-lock.json
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/default.conf.template /etc/nginx/templates/default.conf.template
COPY --from=build /app/dist/weather/browser /usr/share/nginx/html
# Expose the default nginx port
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Aplikacje klienckie są obecnie skonfigurowane do uruchamiania jako prawdziwe aplikacje SPA i nie są skonfigurowane do uruchamiania w trybie renderowania po stronie serwera (SSR). Znajdują się one za nginx, który służy do obsługi plików statycznych. Używają pliku default.conf.template, aby skonfigurować serwer nginx jako pośrednik dla żądań do aplikacji klienckiej.
server {
listen ${PORT};
listen [::]:${PORT};
server_name localhost;
access_log /var/log/nginx/server.access.log main;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass ${services__weatherapi__https__0};
proxy_http_version 1.1;
proxy_ssl_server_name on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
rewrite ^/api(/.*)$ $1 break;
}
}
Zagadnienia dotyczące aplikacji serwera Node.js
Chociaż ten artykuł koncentruje się na aplikacjach klienckich, mogą istnieć scenariusze, w których trzeba hostować aplikację serwera Node.js. Ta sama semantyka jest wymagana do hostowania aplikacji serwera Node.js jako aplikacji klienckiej SPA. Host aplikacji .NET.NET Aspire wymaga odwołania do pakietu NuGet Aspire.Hosting.NodeJS, a kod musi wywołać AddNodeApp
lub AddNpmApp
. Te interfejsy API są przydatne do dodawania istniejących aplikacji JavaScript do hosta aplikacji .NET.NET Aspire.
Podczas konfigurowania tajnych danych i przekazywania zmiennych środowiskowych do aplikacji opartych na języku JavaScript, niezależnie od tego, czy są to aplikacje klienckie czy serwerowe, używaj parametrów. Aby uzyskać więcej informacji, zapoznaj się z .NET.NET Aspire: Parametry zewnętrzne — tajne.
Korzystanie z zestawu SDK języka JavaScript OpenTelemetry
Aby wyeksportować dzienniki OpenTelemetry, ślady i metryki z aplikacji serwerowej Node.js, używasz zestawu SDK OpenTelemetry JavaScript.
Pełny przykład aplikacji serwera Node.js przy użyciu JavaScript SDK OpenTelemetry można znaleźć na stronie Przykłady kodu: .NET AspireNode.js. Rozważmy plik instrumentation.js przykładu, który pokazuje, jak skonfigurować zestaw SDK języka JavaScript OpenTelemetry do eksportowania dzienników, śladów i metryk:
import { env } from 'node:process';
import { NodeSDK } from '@opentelemetry/sdk-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-grpc';
import { SimpleLogRecordProcessor } from '@opentelemetry/sdk-logs';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
import { RedisInstrumentation } from '@opentelemetry/instrumentation-redis-4';
import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api';
import { credentials } from '@grpc/grpc-js';
const environment = process.env.NODE_ENV || 'development';
// For troubleshooting, set the log level to DiagLogLevel.DEBUG
//diag.setLogger(new DiagConsoleLogger(), environment === 'development' ? DiagLogLevel.INFO : DiagLogLevel.WARN);
const otlpServer = env.OTEL_EXPORTER_OTLP_ENDPOINT;
if (otlpServer) {
console.log(`OTLP endpoint: ${otlpServer}`);
const isHttps = otlpServer.startsWith('https://');
const collectorOptions = {
credentials: !isHttps
? credentials.createInsecure()
: credentials.createSsl()
};
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter(collectorOptions),
metricReader: new PeriodicExportingMetricReader({
exportIntervalMillis: environment === 'development' ? 5000 : 10000,
exporter: new OTLPMetricExporter(collectorOptions),
}),
logRecordProcessor: new SimpleLogRecordProcessor({
exporter: new OTLPLogExporter(collectorOptions)
}),
instrumentations: [
new HttpInstrumentation(),
new ExpressInstrumentation(),
new RedisInstrumentation()
],
});
sdk.start();
}
Napiwek
Aby skonfigurować ustawienia CORS OTEL dla pulpitu nawigacyjnego .NET.NET Aspire, zobacz stronę ustawień CORS OTEL pulpitu nawigacyjnego .NET.NET Aspire.
Streszczenie
Chociaż istnieje kilka zagadnień wykraczających poza zakres tego artykułu, przedstawiono sposób tworzenia projektów .NET Aspire korzystających z Node.js i Menedżera pakietów węzłów (npm
). Pokazano również, jak używać interfejsów API AddNpmApp do hostowania Node.js aplikacji i aplikacji wykonywanych odpowiednio z pliku package.json. Na koniec przedstawiono sposób używania interfejsu wiersza polecenia npm
do tworzenia Angular, Reacti Vue aplikacji klienckich oraz konfigurowania ich do uruchamiania na różnych portach.
Zobacz też
- przykłady kodu : .NET Aspire z Angular, Reacti Vue
- Przykłady kodu: .NET AspireNode.js Aplikacja