Orkiestracja aplikacji Node.js w .NET Aspire
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 pokazuje środowiska Angular, Reacti Vue,client. Następujące interfejsy API .NET.NET Aspire istnieją, aby obsługiwać te scenariusze — i są one częścią Aspire. Hosting.NodeJS pakiet NuGet:
Różnica między tymi dwoma interfejsami API polega na tym, że pierwszy jest używany do hostowania aplikacji Node.js, podczas gdy ten ostatni służy do hostowania aplikacji wykonywanych z pakietu . Sekcja scripts
plikujson oraz odpowiadające jej polecenie 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 elementach frontendu aplikacji Single-Page (SPA), na stronie z przykładami kodu znajduje się dodatkowy przykład Node.js: .NET AspireNode.js, który pokazuje, jak używać Node.js jako aplikacji server z użyciem 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 istnieje sześć katalogów podrzędnych opisanych na poniższej liście:
- 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 wykorzystuje API prognozy pogody i wyświetla dane w tabeli.
Instalowanie zależności client
Przykładowa aplikacja pokazuje, jak używać aplikacji client JavaScript opartych na Node.js. Każda aplikacja client 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 client 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 client. W tym celu przejdź do każdego folderu client i uruchom polecenia npm install
(lub aliasu instalacji npm i
).
Instalowanie zależności Angular
npm i ./AspireJavaScript.Angular/
Aby uzyskać więcej informacji na temat aplikacji Angular, sprawdź i przeanalizuj Angularclient.
Instalowanie zależności React
npm i ./AspireJavaScript.React/
Aby uzyskać więcej informacji na temat aplikacji React, zobacz i zbadaj Reactclient.
Instalowanie zależności Vue
npm i ./AspireJavaScript.Vue/
Aby uzyskać więcej informacji na temat aplikacji Vue, zobacz i eksploruj Vueclient.
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
Punkt końcowy usługi weatherapi
prowadzi do strony Swagger UI dokumentującej interfejs API HTTP. Każda aplikacja client używa tej usługi do wyświetlania danych prognozy pogody. Każdą aplikację client można wyświetlić, przechodząc do odpowiedniego punktu końcowego na pulpicie nawigacyjnym .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 client 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.0.0" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.0.0" />
<PackageReference Include="Aspire.Hosting.NodeJs" Version="9.0.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 client 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 do hosta aplikacji.
- Oznacza punkty końcowe HTTP jako zewnętrzne.
- Z odwołaniem do usługi "weatherapi" dodaje "angular", "react", i "vue" client jako aplikacje npm.
- Każda aplikacja client jest skonfigurowana do uruchamiania na innym porcie kontenera i używa zmiennej środowiskowej
PORT
do określenia portu. - Wszystkie aplikacje client również polegają na Dockerfile do tworzenia obrazu kontenera i są skonfigurowane do wyrażania siebie w manifeście publikowania jako kontenera z interfejsu API PublishAsDockerFile.
- Każda aplikacja client 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 client, używa polecenia npm run start
. To polecenie jest definiowane w sekcji scripts
pakietu .json plik dla każdej aplikacji client. Skrypt start
służy do uruchamiania aplikacji client na określonym porcie. Każda aplikacja client korzysta z serwera proxy, aby zażądać usługi "weatherapi".
Serwer proxy jest skonfigurowany w:
- Plik proxy.conf.js dla Angularclient.
- Plik webpack.config.js dla Reactclient.
- Plik vite.config.ts dla Vueclient.
Eksploruj Angularclient
Istnieje kilka kluczowych modyfikacji oryginalnego szablonu Angular. Pierwszy to dodanie pliku proxy.conf.js. Ten plik jest używany do proxy'owania żądań z Angularclient 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.
Druga aktualizacja dotyczy pakietu , plikujson. Ten plik służy do konfigurowania Angularclient 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": "^18.1.1",
"@angular/common": "^18.1.1",
"@angular/compiler": "^18.1.1",
"@angular/core": "^18.1.1",
"@angular/forms": "^18.1.1",
"@angular/platform-browser": "^18.1.1",
"@angular/platform-browser-dynamic": "^18.1.1",
"@angular/router": "^18.1.1",
"rxjs": "~7.8.0",
"tslib": "^2.6.3",
"zone.js": "~0.14.8"
},
"devDependencies": {
"@angular-devkit/build-angular": "^18.1.1",
"@angular/cli": "^18.1.1",
"@angular/compiler-cli": "^18.1.1",
"@types/jasmine": "~5.1.0",
"jasmine-core": "~5.2.0",
"karma": "~6.4.3",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.5.3",
"run-script-os": "^1.1.6"
}
}
Sekcja scripts
pakietu . plikjson służy do definiowania skryptu start
. Ten skrypt jest używany przez polecenie npm start
, aby uruchomić aplikację Angularclient. 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 Angularclient musi być skonfigurowana tak, 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 Angularclient musi wywołać punkt końcowy /api/WeatherForecast
, aby pobrać dane 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ę Angularclient, przejdź do punktu końcowego "angular" na pulpicie nawigacyjnym .NET Aspire. Na poniższej ilustracji przedstawiono aplikację Angularclient:
Eksplorowanie Reactclient
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 aplikacji Reactclient. 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. - Wyniki
znajdują się w folderze zawierającym 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 uruchomiona aplikacja
Aby zwizualizować aplikację Reactclient, przejdź do punktu końcowego "react" na pulpicie nawigacyjnym .NET Aspire. Na poniższej ilustracji przedstawiono aplikację Reactclient:
Eksplorowanie Vueclient
Istnieje kilka kluczowych modyfikacji oryginalnego szablonu Vue. Podstawowe aktualizacje obejmowały dodanie wywołania fetch
w pliku TheWelcomevue, 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 server, aplikacja Vueclient 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 uruchomiona aplikacja
Aby zwizualizować aplikację Vueclient, przejdź do punktu końcowego "vue" na pulpicie nawigacyjnym .NET Aspire. Na poniższej ilustracji przedstawiono aplikację Vueclient:
Zagadnienia dotyczące wdrażania
Przykładowy kod źródłowy tego artykułu jest przeznaczony do uruchamiania lokalnie. Każda aplikacja client jest wdrażana jako obraz kontenera. Dockerfile dla każdej aplikacji client 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 client są obecnie skonfigurowane do uruchamiania jako aplikacje SPA i nie są skonfigurowane do uruchamiania z renderowaniem po stronie server(SSR). Znajdują się one za nginx, który służy do obsługi plików statycznych. Używają pliku
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;
}
}
Node.js server zagadnienia dotyczące aplikacji
Chociaż ten artykuł koncentruje się na aplikacjach client, mogą wystąpić sytuacje, w których trzeba hostować aplikację Node.jsserver. Taka sama semantyka jest wymagana do hostowania aplikacji Node.jsserver jako aplikacji SPA client. Host aplikacji .NET.NET Aspire wymaga odwołania do pakietu Aspirepakietu NuGet Hosting.NodeJS i 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 tajemnic i przekazywania zmiennych środowiskowych do aplikacji opartych na JavaScript, niezależnie od tego, czy są to aplikacje client, czy server, powinny być użyte parametry. 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 Node.jsserver, należy użyć JavaScript SDK OpenTelemetry.
Kompletny przykład aplikacji Node.jsserver korzystających z zestawu SDK języka JavaScript OpenTelemetry można znaleźć na stronie przykładów kodu : .NET AspireNode.js przykładowej strony. 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
). Nauczyłeś się również, jak używać interfejsów API AddNpmApp do hostowania aplikacji Node.js oraz aplikacji wykonywanych z pakietu . Plikjson, odpowiednio. Na koniec przedstawiono sposób używania interfejsu wiersza polecenia npm
do tworzenia Angular, Reacti Vueclient aplikacji 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