Delen via


Apps Node.js in .NET Aspire organiseren

In dit artikel leert u hoe u Node.js- en Node Package Manager-apps (npm) gebruikt in een .NET.NET Aspire project. De voorbeeld-app in dit artikel laat zien Angular, Reacten Vue clientervaringen. De volgende .NET.NET Aspire API's bestaan om deze scenario's te ondersteunen, en ze maken deel uit van de Aspire. Hosting.NodeJS NuGet-pakket:

Het verschil tussen deze twee API's is dat de eerste wordt gebruikt voor het hosten van Node.js-apps, terwijl de laatste wordt gebruikt voor het hosten van apps die worden uitgevoerd vanuit de scripts-sectie van een package.json-bestand en de bijbehorende npm run <script-name>-opdracht.

Tip

De voorbeeldbroncode voor dit artikel is beschikbaar op GitHuben er zijn details beschikbaar op de Codevoorbeelden: .NET Aspire met Angular, React en Vue pagina.

Belangrijk

Hoewel dit artikel is gericht op de (SPA) frontend-gedeeltes van de Single-Page App, is er een extra Node.js voorbeeld beschikbaar op de pagina van de codevoorbeelden: het .NET AspireNode.js voorbeeld, dat laat zien hoe u Node.js als een server-app kunt gebruiken met express.

Voorwaarden

Als u met .NET.NET Aspirewilt werken, hebt u het volgende lokaal geïnstalleerd:

Zie .NET.NET Aspire setup en hulpprogramma'sen .NET.NET Aspire SDK-voor meer informatie.

Daarnaast moet u Node.js installeren op uw computer. De voorbeeld-app in dit artikel is gebouwd met Node.js versie 20.12.2 en npm versie 10.5.1. Voer de volgende opdrachten uit om uw Node.js- en NPM-versies te controleren:

node --version
npm --version

Als u Node.js (inclusief npm) wilt downloaden, raadpleegt u de Node.js downloadpagina.

Voorbeeldbroncode klonen

Voer de volgende opdracht uit om de voorbeeldbroncode uit GitHubte klonen:

git clone https://github.com/dotnet/aspire-samples.git

Navigeer na het klonen van de opslagplaats naar de map samples/AspireWithJavaScript map:

cd samples/AspireWithJavaScript

Vanuit deze map zijn er zes submappen beschreven in de volgende lijst.

  • AspireJavaScript.Angular: een Angular-app die de API voor weersvoorspelling gebruikt en de gegevens in een tabel weergeeft.
  • AspireJavaScript.AppHost: een .NET.NET Aspire project waarmee de andere apps in dit voorbeeld worden ingedeeld. Voor meer informatie, zie .NET.NET Aspire orchestratieoverzicht.
  • AspireJavaScript.MinimalApi: een HTTP-API die willekeurig gegenereerde weersvoorspellingsgegevens retourneert.
  • AspireJavaScript.React: een React-app die de API voor weersvoorspelling gebruikt en de gegevens in een tabel weergeeft.
  • AspireJavaScript.ServiceDefaults: het standaard gedeelde project voor .NET.NET Aspire projecten. Zie .NET.NET Aspire servicestandaardenvoor meer informatie.
  • AspireJavaScript.Vue: een Vue-app die de API voor weersvoorspelling gebruikt en de gegevens in een tabel weergeeft.

Clientafhankelijkheden installeren

De voorbeeld-app laat zien hoe u JavaScript-client-apps gebruikt die zijn gebouwd op Node.js. Elke client-app is geschreven met behulp van een npm create sjabloonopdracht of handmatig. De volgende tabel bevat de sjabloonopdrachten die worden gebruikt om elke client-app te maken, samen met de standaardpoort:

App-type Opdracht Sjabloon maken Standaardpoort
Angular npm create @angular@latest 4200
React Er is geen sjabloon gebruikt. PORT env var
Vue npm create vue@latest 5173

Tip

U hoeft geen van deze opdrachten uit te voeren, omdat de voorbeeld-app al de clients bevat. In plaats daarvan is dit een referentiepunt waaruit de klanten zijn voortgekomen. Zie npm-init-voor meer informatie.

Als u de app wilt uitvoeren, moet u eerst de afhankelijkheden voor elke client installeren. Hiervoor gaat u naar elke clientmap en voert u npm install (of de installatiealias npm i) uit.

Afhankelijkheden Angular installeren

npm i ./AspireJavaScript.Angular/

Zie de Angular-clientverkennen voor meer informatie over de Angular-app.

Afhankelijkheden React installeren

npm i ./AspireJavaScript.React/

Zie de React-clientverkennen voor meer informatie over de React-app.

Afhankelijkheden Vue installeren

npm i ./AspireJavaScript.Vue/

Zie de Vue-clientverkennen voor meer informatie over de Vue-app.

De voorbeeld-app uitvoeren

Als u de voorbeeld-app wilt uitvoeren, roept u het commando dotnet run aan, waarbij de orchestrator-app-versie AspireJavaScript.AppHost.csproj wordt gebruikt als de --project-switch.

dotnet run --project ./AspireJavaScript.AppHost/AspireJavaScript.AppHost.csproj

Het .NET.NET Aspire-dashboard wordt in uw standaardbrowser gestart en elk eindpunt van de client-app wordt weergegeven in de kolom Eindpunten op de pagina Resources. In de volgende afbeelding ziet u het dashboard voor deze voorbeeld-app:

.NET.NET Aspire dashboard met meerdere JavaScript-client-apps.

Het weatherapi service-eindpunt leidt naar een Swagger UI-pagina die de HTTP-API documenteert. Elke client-app gebruikt deze service om de weersvoorspellingsgegevens weer te geven. U kunt elke client-app bekijken door naar het bijbehorende eindpunt te navigeren in het .NET.NET Aspire dashboard. De schermopnamen en de wijzigingen die zijn aangebracht op basis van het sjabloonstartpunt, worden in de volgende secties beschreven.

Druk in dezelfde terminalsessie die u hebt gebruikt om de app uit te voeren op Ctrl + C- om de app te stoppen.

De app-host verkennen

Als u wilt weten hoe elke client-app-resource wordt ingedeeld, kijkt u naar het app-hostproject. De app-host vereist het NuGet-pakket Aspire. Hosting.NodeJS om Node.js apps te hosten.

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

  <Sdk Name="Aspire.AppHost.Sdk" Version="9.1.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.1.0" />
    <PackageReference Include="Aspire.Hosting.NodeJs" Version="9.1.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>

Het projectbestand definieert ook een builddoel dat ervoor zorgt dat de npm-afhankelijkheden worden geïnstalleerd voordat de app-host wordt gebouwd. De app-hostcode (Program.cs) declareert de resources van de client-app met behulp van de AddNpmApp(IDistributedApplicationBuilder, String, String, String, String[])-API.

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();

De voorgaande code:

  • Hiermee maakt u een DistributedApplicationBuilder.
  • Voegt de 'weatherapi'-service als een project toe aan de app-host.
    • Markeert de HTTP-eindpunten als extern.
  • Met een verwijzing naar de 'weatherapi'-service voegt u de client-apps 'angular', 'react' en 'vue' toe als npm-apps.
    • Elke client-app is geconfigureerd voor uitvoering op een andere containerpoort en gebruikt de omgevingsvariabele PORT om de poort te bepalen.
    • Alle client-apps zijn ook afhankelijk van een Dockerfile om hun containerafbeeldingen te bouwen en zijn geconfigureerd om zichzelf te presenteren in het publicatiemanifest als een container van de PublishAsDockerFile-API.

Voor meer informatie over interne-lusnetwerken, zie .NET.NET Aspire overzicht van interne-lusnetwerken. Voor meer informatie over het implementeren van apps, zie .NET.NET Aspire manifestindeling voor implementatietoolbouwers.

Wanneer de app-host het starten van elke client-app organiseert, wordt de opdracht npm run start gebruikt. Deze opdracht wordt gedefinieerd in de sectie scripts van het package.json-bestand voor elke client-app. Het start script wordt gebruikt om de client-app op de opgegeven poort te starten. Elke client-app is afhankelijk van een proxy om de 'weatherapi'-service aan te vragen.

De proxy is geconfigureerd in:

  • Het proxy.conf.js-bestand voor de Angular-client.
  • Het webpack.config.js-bestand voor de React-client.
  • Het vite.config.ts-bestand voor de Vue-client.

De Angular-client verkennen

Er zijn verschillende belangrijke wijzigingen van de oorspronkelijke Angular-sjabloon. De eerste is het toevoegen van een proxy.conf.js bestand. Dit bestand wordt gebruikt voor proxyaanvragen van de Angular-client naar de 'weatherapi'-service.

module.exports = {
  "/api": {
    target:
      process.env["services__weatherapi__https__0"] ||
      process.env["services__weatherapi__http__0"],
    secure: process.env["NODE_ENV"] !== "development",
    pathRewrite: {
      "^/api": "",
    },
  },
};

De .NET.NET Aspire-app-host stelt de services__weatherapi__http__0 omgevingsvariabele in, die wordt gebruikt om het service-eindpunt 'weatherapi' op te lossen. De voorgaande configuratieproxy's sturen HTTP-verzoeken die beginnen met /api door naar de doel-URL die is opgegeven in de omgevingsvariabele.

Voeg vervolgens het proxybestand toe aan het angular.json-bestand. Werk het serve doel bij om de proxyConfig optie op te nemen, die verwijst naar het gemaakte proxy.conf.js-bestand. De Angular CLI gebruikt nu de proxyconfiguratie tijdens het leveren van de Angular client-app.

"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"
  }
},

De derde update is naar het package.json-bestand. Dit bestand wordt gebruikt om de Angular-client te configureren voor uitvoering op een andere poort dan de standaardpoort. Dit wordt bereikt met behulp van de omgevingsvariabele PORT en het run-script-os npm-pakket om de poort in te stellen.

{
  "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"
  }
}

De scripts sectie van het package.json-bestand wordt gebruikt om het start script te definiëren. Dit script wordt gebruikt door de opdracht npm start om de Angular-client-app te starten. Het start-script is geconfigureerd om het run-script-os-pakket te gebruiken om de poort in te stellen, waarbij het wordt gedelegeerd aan de ng serve-opdracht die de juiste --port-switch doorgeeft op basis van de syntaxis van het besturingssysteem.

Als u HTTP-aanroepen wilt uitvoeren naar de 'weatherapi'-service, moet de Angular-client-app worden geconfigureerd om de AngularHttpClient voor afhankelijkheidsinjectie te bieden. Dit wordt bereikt met behulp van de provideHttpClient helperfunctie tijdens het configureren van de toepassing in het app.config.ts-bestand.

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()
  ]
};

Ten slotte moet de Angular client-app het /api/WeatherForecast-eindpunt aanroepen om de weersvoorspellingsgegevens op te halen. Er zijn verschillende HTML-, CSS- en TypeScript-updates, die allemaal worden aangebracht in de volgende bestanden:

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 app draait

Als u de Angular-client-app wilt visualiseren, gaat u naar het eindpunt 'angular' in het .NET Aspire-dashboard. In de volgende afbeelding ziet u de Angular client-app:

Angular client-app met valse weersvoorspellingen die als een tabel worden weergegeven.

De React-client verkennen

De React-app is niet geschreven met behulp van een sjabloon en in plaats daarvan handmatig geschreven. De volledige broncode is te vinden in de dotnet/aspire-samples opslagplaats. Enkele belangrijke bezienswaardigheden vindt u in het bestand 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;

De App-functie is het toegangspunt voor de React-client-app. Het maakt gebruik van de useState en useEffect hooks om de status van de weersvoorspellingsgegevens te beheren. De fetch-API wordt gebruikt om een HTTP-aanvraag naar het /api/WeatherForecast-eindpunt te verzenden. Het antwoord wordt vervolgens geconverteerd naar JSON en ingesteld als de status van de weersvoorspellingsgegevens.

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"],
        },
      ],
    },
  };
};

De voorgaande code definieert de module.exports als volgt:

  • De eigenschap entry is ingesteld op het bestand src/index.js.
  • De devServer is afhankelijk van een proxy om aanvragen door te sturen naar de 'weatherapi'-service, stelt de poort in op de omgevingsvariabele PORT en staat alle hosts toe.
  • De output resulteert in een dist map met een bundle.js bestand.
  • Stel plugins het src/index.html-bestand in als sjabloon en stel het favicon.ico-bestand beschikbaar.

De laatste updates zijn voor de volgende bestanden:

React app draait

Als u de React-client-app wilt visualiseren, gaat u naar het eindpunt 'react' in het .NET Aspire-dashboard. In de volgende afbeelding ziet u de React client-app:

React client-app met valse weersvoorspellingen die als een tabel worden weergegeven.

De Vue-client verkennen

Er zijn verschillende belangrijke wijzigingen van de oorspronkelijke Vue-sjabloon. De primaire updates waren de toevoeging van de fetch-aanroep in het bestand TheWelcome.vue om de weervoorspellingsgegevens op te halen uit het /api/WeatherForecast-eindpunt. In het volgende codefragment ziet u de fetch aanroep:

<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>

Omdat de TheWelcome-integratie mountedis, wordt het /api/weatherforecast eindpunt aanroepen om de weersvoorspellingsgegevens op te halen. Het antwoord wordt vervolgens ingesteld als de forecasts-eigenschap voor gegevens. De Vue-client-app gebruikt de omgevingsvariabele PORT om de serverpoort in te stellen. Dit wordt bereikt door het vite.config.ts-bestand bij te werken:

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
      }
    }
  }
})

Daarnaast geeft de vite-configuratie de eigenschap server.proxy op om aanvragen door te sturen naar de 'weatherapi'-service. Dit wordt bereikt met behulp van de services__weatherapi__http__0 omgevingsvariabele, die wordt ingesteld door de .NET.NET Aspire app-host.

De laatste update van de sjabloon wordt gemaakt in het bestand TheWelcome.vue. Dit bestand roept het /api/WeatherForecast-eindpunt aan om de weersvoorspellingsgegevens op te halen en de gegevens in een tabel weer te geven. Het bevat CSS-, HTML- en TypeScript-updates.

Vue app is aan het draaien

Als u de Vue-client-app wilt visualiseren, gaat u naar het eindpunt 'vue' in het .NET Aspire-dashboard. In de volgende afbeelding ziet u de Vue client-app:

Vue client-app met valse weersvoorspellingen die als een tabel worden weergegeven.

Overwegingen bij de implementatie

De voorbeeldbroncode voor dit artikel is ontworpen om lokaal te worden uitgevoerd. Elke client-applicatie wordt uitgevoerd als een container-image. De Dockerfile voor elke client-app wordt gebruikt om de containerafbeelding te bouwen. Elke Dockerfile is identiek en gebruikt een multistage build om een containerafbeelding te maken die gereed is voor productie.

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;"]

De client-apps zijn momenteel geconfigureerd om als echte SPA-toepassingen te draaien en zijn niet geconfigureerd om in een server-side rendering (SSR) modus te draaien. Ze zitten achter nginx, die wordt gebruikt om de statische bestanden te bedienen. Ze gebruiken een default.conf.template-bestand om nginx- te configureren voor proxyaanvragen naar de client-app.

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;
    }
}

Overwegingen met betrekking tot Node.js server-apps

Hoewel dit artikel is gericht op client-apps, hebt u mogelijk scenario's waarin u een Node.js server-app moet hosten. Dezelfde semantiek is vereist voor het hosten van een Node.js-serverapp als van een SPA-clientapp. De .NET.NET Aspire app-host vereist een pakketreferentie naar het Aspire.Hosting.NodeJS NuGet-pakket en de code moet AddNodeApp of AddNpmAppaanroepen. Deze API's zijn handig voor het toevoegen van bestaande JavaScript-apps aan de .NET.NET Aspire app-host.

Bij het configureren van geheimen en het doorgeven van omgevingsvariabelen aan op JavaScript gebaseerde apps, ongeacht of het client- of server-apps zijn, gebruikt u parameters. Zie voor meer informatie .NET.NET Aspire: Externe parameters, geheimen.

De OpenTelemetry JavaScript SDK gebruiken

Als u OpenTelemetry logboeken, traceringen en metrische gegevens uit een Node.js server-app wilt exporteren, gebruikt u de OpenTelemetry JavaScript SDK-.

Voor een volledig voorbeeld van een Node.js-server-app met behulp van de OpenTelemetry JavaScript SDK kunt u verwijzen naar de codevoorbeelden: .NET AspireNode.js voorbeeldpagina van. Bekijk het instrumentation.js-bestand van het voorbeeld, waarin wordt gedemonstreert hoe u de OpenTelemetry JavaScript SDK configureert voor het exporteren van logboeken, traceringen en metrische gegevens:

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();
}

Tip

Zie de .NET pagina om de .NET Aspire dashboard OTEL CORS-instellingen te configureren.

Samenvatting

Hoewel er verschillende overwegingen zijn die buiten het bereik van dit artikel vallen, hebt u geleerd hoe u .NET Aspire projecten bouwt die gebruikmaken van Node.js en Node Package Manager (npm). U hebt ook geleerd hoe u de AddNpmApp API's gebruikt voor het hosten van Node.js apps en apps die worden uitgevoerd vanuit een package.json bestand. Ten slotte hebt u geleerd hoe u de npm CLI kunt gebruiken om Angular, Reacten Vue client-apps te maken en hoe u deze configureert voor uitvoering op verschillende poorten.

Zie ook