Compartilhar via


Orquestrar os aplicativos Node.js no .NET Aspire

Neste artigo, você aprenderá a usar aplicativos Node.js e Node Package Manager (npm) em um projeto .NET.NET Aspire. O aplicativo de exemplo neste artigo demonstra as experiências de Angular, Reacte Vueclient. As APIs de .NET.NET Aspire a seguir existem para dar suporte a esses cenários e fazem parte do Aspire. Host.NodeJS pacote NuGet:

A diferença entre essas duas APIs é que a primeira é usada para hospedar aplicativos Node.js, enquanto a segunda é empregada para hospedar aplicativos que são executados a partir de um pacote . A seção scripts do arquivojson e o comando correspondente npm run <script-name>.

Dica

O código-fonte de exemplo deste artigo está disponível em GitHube há detalhes disponíveis nos exemplos de código : .NET Aspire com Angular, React e Vue página.

Importante

Embora este artigo esteja focado em bits de front-end do Single-Page App (SPA), há um exemplo de Node.js adicional disponível nos exemplos de código : .NET AspireNode.js página de exemplo, que demonstra como usar Node.js como um aplicativo server com express.

Pré-requisitos

Para trabalhar com .NET.NET Aspire, você precisa do seguinte instalado localmente:

Para obter mais informações, consulte .NET.NET Aspirede instalação e ferramentas e .NET.NET Aspiredo SDK.

Além disso, você precisa instalar Node.js em seu computador. O aplicativo de exemplo neste artigo foi criado com Node.js versão 20.12.2 e npm versão 10.5.1. Para verificar as versões Node.js e npm, execute os seguintes comandos:

node --version
npm --version

Para baixar Node.js (incluindo npm), consulte a página de download Node.js.

Clonar código-fonte de exemplo

Para clonar o código-fonte de exemplo de GitHub, execute o seguinte comando:

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

Depois de clonar o repositório, navegue até a pasta samples/AspireWithJavaScript:

cd samples/AspireWithJavaScript

Neste diretório, há seis diretórios filho descritos na seguinte lista:

  • AspireJavaScript.Angular: um aplicativo Angular que consome a API de previsão do tempo e exibe os dados em uma tabela.
  • AspireJavaScript.AppHost: um projeto .NET.NET Aspire que orquestra os outros aplicativos neste exemplo. Para obter mais informações, consulte a visão geral da orquestração .NET.NET Aspire.
  • AspireJavaScript.MinimalApi: uma API HTTP que retorna dados de previsão do tempo gerados aleatoriamente.
  • AspireJavaScript.React: um aplicativo React que consome a API de previsão do tempo e exibe os dados em uma tabela.
  • AspireJavaScript.ServiceDefaults: o projeto compartilhado padrão para projetos .NET.NET Aspire. Para obter mais informações, consulte .NET.NET Aspire padrões de serviço.
  • AspireJavaScript.Vue: um aplicativo Vue que consome a API de previsão do tempo e exibe os dados em uma tabela.

Instalar dependências de client

O aplicativo de exemplo demonstra como usar aplicativos JavaScript client que são criados com base em Node.js. Cada aplicativo client foi escrito usando um comando de modelo npm create ou manualmente. A tabela a seguir lista os comandos de modelo usados para criar cada aplicativo client, juntamente com a porta padrão:

Tipo de aplicativo Criar comando de modelo Porta padrão
Angular npm create @angular@latest 4200
React Eu não usei um modelo. PORT env var
Vue npm create vue@latest 5173

Dica

Você não precisa executar nenhum desses comandos, pois o aplicativo de exemplo já inclui os clientes. Em vez disso, esse é um ponto de referência a partir do qual os clientes foram criados. Para obter mais informações, consulte npm-init.

Para executar o aplicativo, você precisa primeiro instalar as dependências para cada client. Para fazer isso, navegue até cada pasta client e execute npm install (ou os comandos de alias de instalação npm i).

Instalar dependências de Angular

npm i ./AspireJavaScript.Angular/

Para obter mais informações sobre o aplicativo Angular, consulte o para explorar o Angularclient.

Instalar dependências do React

npm i ./AspireJavaScript.React/

Para obter mais informações sobre o aplicativo React, consulte e explore o Reactclient.

Instalar dependências do Vue

npm i ./AspireJavaScript.Vue/

Para obter mais informações sobre o aplicativo Vue, consulte para explorar o Vueclient.

Executar o aplicativo de exemplo

Para executar o aplicativo de exemplo, chame o comando dotnet run dado o host do aplicativo de orquestrador AspireJavaScript.AppHost.csproj como a opção --project:

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

O painel é iniciado no navegador padrão e cada ponto de extremidade do aplicativo é exibido na coluna pontos de extremidade da página recursos do . A imagem a seguir ilustra o painel deste aplicativo de exemplo:

.NET Aspire painel com vários aplicativos client JavaScript.

O ponto de extremidade de serviço weatherapi direciona para uma página do Swagger UI que documenta a API HTTP. Cada aplicativo client consome esse serviço para exibir os dados de previsão do tempo. Você pode exibir cada aplicativo client navegando até o endpoint correspondente no painel .NET Aspire. Suas capturas de tela e as modificações feitas do ponto de partida do modelo são detalhadas nas seções a seguir.

Na mesma sessão de terminal que você usou para executar o aplicativo, pressione Ctrl + C para interromper o aplicativo.

Explorar o host do aplicativo

Para ajudar a entender como cada recurso do aplicativo client é orquestrado, consulte o projeto anfitrião do aplicativo. O host do aplicativo requer o Aspire. Hosting.NodeJS pacote NuGet para hospedar aplicativos 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>

O arquivo de projeto também define um destino de build que garante que as dependências npm sejam instaladas antes da criação do host do aplicativo. O código do host do aplicativo (Program.cs) declara os recursos do aplicativo client usando a 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();

O código anterior:

  • Cria um DistributedApplicationBuilder.
  • Adiciona o serviço "weatherapi" como um projeto ao host do aplicativo.
    • Marca os pontos de extremidade HTTP como externos.
  • Com uma referência ao serviço "weatherapi", adiciona os aplicativos "angular", "react" e "vue" client como aplicativos npm.
    • Cada aplicativo client é configurado para ser executado em uma porta de contêiner diferente e usa a variável de ambiente PORT para determinar a porta.
    • Todos os aplicativos client também dependem de um Dockerfile para criar sua imagem de contêiner e são configurados para se expressarem no manifesto de publicação como um contêiner da API PublishAsDockerFile.

Para obter mais informações sobre rede de loop interno, consulte .NET.NET Aspire visão geral da rede de loop interno. Para obter mais informações sobre como implantar aplicativos, consulte .NET.NET Aspire formato de manifesto para construtores de ferramentas de implantação.

Quando o host do aplicativo orquestra a inicialização de cada aplicativo client, ele usa o comando npm run start. Esse comando é definido na seção scripts do pacote .json arquivo para cada aplicativo client. O script start é usado para iniciar o aplicativo client na porta especificada. Cada aplicativo client depende de um proxy para solicitar o serviço "weatherapi".

O proxy está configurado em:

  • O arquivo proxy.conf.js do Angularclient.
  • O arquivo webpack.config.js do Reactclient.
  • O arquivo vite.config.ts do Vueclient.

Explorar o Angularclient

Há várias modificações importantes do modelo de Angular original. A primeira é a adição de um arquivo proxy.conf.js. Esse arquivo é usado para redirecionar solicitações do Angularclient para o serviço "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": "",
    },
  },
};

O host do aplicativo .NET.NET Aspire define a variável de ambiente services__weatherapi__http__0, que é usada para determinar o endpoint do serviço "weatherapi". A configuração antecedente direciona as solicitações HTTP que começam com /api para a URL de destino especificada na variável de ambiente.

A segunda atualização é para o pacote . Arquivojson. Esse arquivo é usado para configurar o Angularclient a ser executado em uma porta diferente da porta padrão. Isso é obtido usando a variável de ambiente PORT e o pacote npm run-script-os para definir a porta.

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

A seção scripts do pacote . O arquivojson é usado para definir o script start. Esse script é usado pelo comando npm start para iniciar o aplicativo Angularclient. O script start é configurado para usar o pacote run-script-os para definir a porta, delegando ao comando ng serve passando o comutador --port apropriado de acordo com a sintaxe apropriada do sistema operacional.

Para fazer chamadas HTTP para o serviço "weatherapi", o aplicativo Angularclient precisa ser configurado para fornecer o AngularHttpClient para injeção de dependência. Isso é obtido usando a função auxiliar provideHttpClient ao configurar o aplicativo no arquivo 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()
  ]
};

Por fim, o aplicativo Angularclient precisa chamar o endpoint /api/WeatherForecast para recuperar os dados de previsão do tempo. Há várias atualizações HTML, CSS e TypeScript, todas feitas nos seguintes arquivos:

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 aplicativo em execução

Para visualizar o aplicativo Angularclient, navegue até o "endpoint"angularno painel .NET Aspire. A imagem a seguir ilustra o aplicativo Angularclient:

Angularclient aplicativo com dados meteorológicos de previsão falsos exibidos como uma tabela.

Explorar os Reactclient

O aplicativo React não foi escrito usando um modelo e, em vez disso, foi escrito manualmente. O código-fonte completo pode ser encontrado no repositório dotnet/aspire-samples. Alguns dos principais pontos de interesse são encontrados no arquivo 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;

A função App é o ponto de entrada do aplicativo Reactclient. Ele usa os ganchos useState e useEffect para gerenciar o estado dos dados de previsão do tempo. A API fetch é usada para fazer uma solicitação HTTP para o endpoint /api/WeatherForecast. Em seguida, a resposta é convertida em JSON e definida como o estado dos dados de previsão do tempo.

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

O código anterior define o module.exports da seguinte maneira:

  • A propriedade entry é configurada para o arquivo src/index.js.
  • O devServer depende de um proxy para encaminhar solicitações para o serviço "weatherapi", configura a porta para a variável de ambiente PORT e permite todos os hosts.
  • O resulta em uma pasta dist com um arquivo bundle.js.
  • O plugins definiu o arquivo src/index.html como o modelo e expôs o arquivo favicon.ico.

As atualizações finais são para os seguintes arquivos:

React aplicativo em execução

Para visualizar o aplicativo Reactclient, navegue até o endpoint "react" no painel .NET Aspire. A imagem a seguir ilustra o aplicativo Reactclient:

Reactclient aplicativo com dados meteorológicos de previsão falsos exibidos como uma tabela.

Explorar Vueclient

Há várias modificações importantes do modelo de Vue original. As atualizações primárias foram a adição da chamada fetch no TheWelcome,vue, para recuperar os dados de previsão do tempo do ponto de extremidade /api/WeatherForecast. O snippet de código a seguir demonstra a chamada 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>

Como a integração TheWelcome é mounted, ela chama o endpoint /api/weatherforecast para obter os dados de previsão do tempo. Em seguida, a resposta é definida como a propriedade de dados forecasts. Para definir a porta server, o aplicativo Vueclient usa a variável de ambiente PORT. Isso é feito atualizando o arquivo 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
      }
    }
  }
})

Além disso, a configuração do Vite especifica a propriedade server.proxy para encaminhar solicitações para o serviço "weatherapi". Isso é obtido usando a variável de ambiente services__weatherapi__http__0, que é definida pelo host do aplicativo .NET.NET Aspire.

A atualização final do modelo é feita no arquivo TheWelcome.vue. Esse arquivo chama o ponto de extremidade /api/WeatherForecast para recuperar os dados de previsão do tempo e exibe os dados em uma tabela. Inclui atualizações de CSS, HTML e TypeScript.

aplicativo Vue em execução

Para visualizar o aplicativo Vueclient, navegue até o endpoint "vue" no painel .NET Aspire. A imagem a seguir ilustra o aplicativo Vueclient:

Vueclient aplicativo com dados meteorológicos de previsão falsos exibidos como uma tabela.

Considerações sobre implantação

O código-fonte de exemplo deste artigo foi projetado para ser executado localmente. Cada aplicativo client é implantado como uma imagem de container. O Dockerfile para cada aplicativo client é usado para criar a imagem do contêiner. Cada Dockerfile é idêntico, usando um build de vários estágios para criar uma imagem de contêiner pronta para produção.

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

Os aplicativos client estão atualmente configurados para serem executados como verdadeiros aplicativos SPA e não estão configurados para serem executados em um modo SSR (renderizado serverlado). Eles estão por trás de nginx, que é usado para servir os arquivos estáticos. Eles usam um arquivo default.conf.template para configurar nginx para solicitações de proxy para o aplicativo .

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 considerações sobre o aplicativo

Embora este artigo se concentre em client aplicativos, você pode ter cenários em que precisa hospedar um aplicativo Node.jsserver. A mesma semântica é necessária para hospedar um aplicativo Node.jsserver como um aplicativo client SPA. O host do aplicativo .NET.NET Aspire requer uma referência de pacote ao Aspire.Hosting.NodeJS pacote NuGet, e o código precisa chamar AddNodeApp ou AddNpmApp. Essas APIs são úteis para adicionar aplicativos JavaScript existentes ao host do aplicativo .NET.NET Aspire.

Ao configurar segredos e passar variáveis de ambiente para aplicativos baseados em JavaScript, sejam eles client ou server aplicativos, use parâmetros. Para obter mais informações, consulte .NET.NET Aspire: Parâmetros externos — segredos.

Usar o SDK do OpenTelemetry JavaScript

Para exportar logs, rastreamentos e métricas de um aplicativo , use odo SDK JavaScript.

Para obter um exemplo completo de um aplicativo Node.jsserver usando o SDK do JavaScript OpenTelemetry, você pode consultar a página de exemplos de código : .NET AspireNode.js. Considere o arquivo instrumentation.js do exemplo, que demonstra como configurar o SDK OpenTelemetry JavaScript para exportar logs, rastreamentos e métricas:

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

Dica

Para definir as configurações do OTEL CORS do painel .NET.NET Aspire, consulte a página de configurações do OTEL CORS do painel .NET.NET Aspire.

Resumo

Embora haja várias considerações que estão além do escopo deste artigo, você aprendeu a criar projetos .NET Aspire que usam Node.js e o Gerenciador de Pacotes do Nó (npm). Você também aprendeu a usar as APIs de AddNpmApp para hospedar aplicativos Node.js e executar aplicativos de um pacote , arquivojson, respectivamente. Por fim, você aprendeu a usar a CLI npm para criar aplicativos Angular, Reacte Vueclient e como configurá-los para serem executados em portas diferentes.

Consulte também