在 .NET Aspire 中协调 Node.js 应用
本文介绍如何在 .NET.NET Aspire 项目中使用 Node.js 和 Node 包管理器(npm
)应用。 本文中的示例应用演示了 Angular、React和 Vueclient 体验。 为了支持这些方案,以下 .NET.NET Aspire API 是 Aspire.Hosting.NodeJS NuGet 包的一部分:
这两个 API 之间的区别在于,前者用于托管 Node.js 应用,而后者用于托管从 包执行的应用。json 文件的 scripts
节和相应的 npm run <script-name>
命令。
提示
本文的示例源代码在 GitHub上提供,代码示例中提供了详细信息:.NET Aspire 包含 Angular、React 和 Vue 页。
重要
虽然本文重点介绍 Single-Page 应用(SPA)的前端部分,但在 代码示例中的 .NET AspireNode.js 示例 页面,提供了一个附加的 Node.js 示例,演示如何将 Node.js 作为 server 应用,并结合 Express 框架。
先决条件
若要使用 .NET.NET Aspire,需要在本地安装以下各项:
- .NET 8.0 或 .NET 9.0
- 符合开放容器协会(OCI)标准的容器运行时,例如:
- 集成开发人员环境(IDE)或代码编辑器,例如:
- Visual Studio 2022 17.9 或更高版本(可选)
-
Visual Studio Code (可选)
- C# Dev Kit:扩展(可选)
- JetBrains Rider 使用 .NET.NET Aspire 插件(可选)
有关详细信息,请参阅 .NET.NET Aspire 设置和工具,以及 .NET.NET Aspire SDK。
此外,需要在计算机上安装 Node.js。 本文中的示例应用是使用 Node.js 版本 20.12.2 和 npm 版本 10.5.1 生成的。 若要验证 Node.js 和 npm 版本,请运行以下命令:
node --version
npm --version
若要下载 Node.js(包括 npm
),请参阅 Node.js 下载页面。
克隆示例源代码
若要从 GitHub克隆示例源代码,请运行以下命令:
git clone https://github.com/dotnet/aspire-samples.git
克隆存储库后,导航到 samples/AspireWithJavaScript 文件夹:
cd samples/AspireWithJavaScript
从这个目录中,有以下列表中描述的六个子目录:
- AspireJavaScript。Angular:使用天气预报 API 并在表中显示数据的 Angular 应用。
- AspireJavaScript.AppHost:协调此示例中其他应用的 .NET.NET Aspire 项目。 有关详细信息,请参阅 .NET.NET Aspire 业务流程概述。
- AspireJavaScript.MinimalApi:返回随机生成的天气预报数据的 HTTP API。
- AspireJavaScript。React:使用天气预报 API 并在表中显示数据的 React 应用。
- AspireJavaScript.ServiceDefaults:.NET.NET Aspire 项目的默认共享项目。 有关详细信息,请参阅 .NET.NET Aspire 服务默认值。
- AspireJavaScript。Vue:使用天气预报 API 并在表中显示数据的 Vue 应用。
安装 client 依赖项
示例应用演示如何使用基于 Node.js构建的 JavaScript client 应用。 每个 client 应用都使用 npm create
模板命令或手动编写。 下表列出了用于创建每个 client 应用的模板命令以及默认端口:
应用类型 | 创建模板命令 | 默认端口 |
---|---|---|
Angular | npm create @angular@latest |
4200 |
React | 未使用模板。 | 端口 env var |
Vue | npm create vue@latest |
5173 |
提示
无需运行这些命令中的任何一个,因为示例应用已包含客户端。 这是用于创建客户端的参考点。 有关详细信息,请参阅 npm-init。
若要运行应用,首先需要为每个 client安装依赖项。 为此,请导航到每个 client 文件夹并运行 npm install
(或安装别名 npm i
)命令。
安装 Angular 依赖项
npm i ./AspireJavaScript.Angular/
有关 Angular 应用的详细信息,请参阅 探索 Angularclient。
安装 React 依赖项
npm i ./AspireJavaScript.React/
有关 React 应用的详细信息,请参阅,并浏览Reactclient。
安装 Vue 依赖项
npm i ./AspireJavaScript.Vue/
有关 Vue 应用的详细信息,请参阅 浏览 Vueclient。
运行示例应用
若要运行示例应用程序,请调用 dotnet run 命令,并将编排应用宿主 AspireJavaScript.AppHost.csproj 作为 --project
切换参数。
dotnet run --project ./AspireJavaScript.AppHost/AspireJavaScript.AppHost.csproj
.NET .NET Aspire 仪表板 会在默认浏览器中打开,每个 client 应用终结点显示在 资源 页的“终结点”列下。 下图描绘了此示例应用的仪表板:
weatherapi
服务端点指向展示 HTTP API 的 Swagger UI 页面。 每个 client 应用使用此服务来显示天气预报数据。 可以通过导航到 .NET Aspire 仪表板中的相应终结点来查看每个 client 应用。 以下部分详细介绍了从模板起点进行的屏幕截图和修改。
在用于运行应用的同一终端会话中,按 Ctrl + C 停止应用。
探索应用主机
为了帮助了解如何协调每个 client 应用资源,请查看应用程序宿主项目。 应用主机需要 Aspire。Hosting.NodeJS NuGet 包来托管 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>
项目文件还定义了一个生成目标,该目标可确保在生成应用主机之前安装 npm 依赖项。 应用主机代码(Program.cs)使用 AddNpmApp(IDistributedApplicationBuilder, String, String, String, String[]) API 声明 client 应用资源。
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();
前面的代码:
- 创建 DistributedApplicationBuilder。
- 将“weatherapi”服务作为项目添加到应用主机。
- 将 HTTP 终结点标记为外部。
- 参考“weatherapi”服务,将“angular”、“react”和“vue”应用以及client应用添加为 npm 应用。
- 每个 client 应用都配置为在不同的容器端口上运行,并使用
PORT
环境变量来确定端口。 - 所有 client 应用还依靠一个 Dockerfile 来构建其容器镜像,并被配置为在发布清单中通过 PublishAsDockerFile API 以容器的形式表示。
- 每个 client 应用都配置为在不同的容器端口上运行,并使用
有关内部循环网络的详细信息,请参阅 .NET.NET Aspire 内部循环网络概述。 有关部署应用的详细信息,请参阅部署工具生成器
当应用主机协调每个 client 应用的启动时,它使用 npm run start
命令。 此命令在 包的 scripts
节中定义。每个 client 应用的json 文件。
start
脚本用于在指定端口上启动 client 应用。 每个 client 应用都依赖于代理来请求“weatherapi”服务。
代理配置在以下位置:
- Angular client的 proxy.conf.js 文件。
- React client的 webpack.config.js 文件。
- Vue client的 vite.config.ts 文件。
浏览 Angularclient
原始 Angular 模板中有几个关键修改。 第一个是添加 proxy.conf.js 文件。 此文件用于将来自 Angularclient 的请求代理到“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": "",
},
},
};
.NET
.NET Aspire 应用主机设置 services__weatherapi__http__0
环境变量,该变量用于解析“weatherapi”服务终结点。 前面的配置将以 /api
开头的 HTTP 请求代理到环境变量中指定的目标 URL。
第二个更新是 包。json 文件。 此文件用于将 Angularclient 配置为在与默认端口不同的端口上运行。 这是通过使用 PORT
环境变量实现的,run-script-os
npm 包用于设置端口。
{
"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"
}
}
包的 scripts
部分。json 文件用于定义 start
脚本。
npm start
命令使用此脚本启动 Angularclient 应用。
start
脚本配置为使用 run-script-os
包来设置端口,它将设置工作委托给 ng serve
命令,后者根据适用于操作系统的语法传递合适的 --port
开关。
若要对“weatherapi”服务进行 HTTP 调用,需要将 Angularclient 应用配置为提供依赖项注入的 AngularHttpClient
。 这是通过使用 provideHttpClient
帮助程序函数在 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()
]
};
最后,Angularclient 应用需要调用 /api/WeatherForecast
终结点来检索天气预报数据。 有多个 HTML、CSS 和 TypeScript 更新,所有这些更新都针对以下文件进行:
- app.component.css:更新 CSS 以设置表格样式。
- app.component.html:更新 HTML 以显示表中的天气预报数据。
-
app.component.ts:更新 TypeScript 代码以调用
/api/WeatherForecast
端点,并在表中显示数据。
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应用正在运行
若要可视化 Angularclient 应用,请导航到 .NET Aspire 仪表板中的“angular”终结点。 下图描述了 Angularclient 应用:
浏览 Reactclient
React 应用未使用模板编写,而是手动编写。 完整的源代码可以在 dotnet/aspire-samples 存储库中找到。 某些关键要点出现在 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;
App
函数是 Reactclient 应用的入口点。 它使用 useState
和 useEffect
这些钩子来管理天气预报数据的状态。
fetch
API 用于向 /api/WeatherForecast
终结点发出 HTTP 请求。 然后,响应将转换为 JSON,并设置为天气预报数据的状态。
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"],
},
],
},
};
};
前面的代码定义 module.exports
,如下所示:
-
entry
属性被设置为 src/index.js 文件。 -
devServer
依赖于代理将请求转发到“weatherapi”服务,将端口设置为PORT
环境变量,并允许所有主机。 -
output
会生成具有 bundle.js 文件的 dist 文件夹。 -
plugins
将 src/index.html 文件设置为模板,并公开 favicon.ico 文件。
最终更新涉及以下文件:
React 应用正在运行
若要可视化 Reactclient 应用,请导航到 .NET Aspire 仪表板中的“react”终结点。 下图描述了 Reactclient 应用:
浏览 Vueclient
原始 Vue 模板中有几个关键修改。 主要更新是在 TheWelcome 中添加 fetch
调用,在vue 文件中,以从 /api/WeatherForecast
终结点检索天气预报数据。 以下代码片段演示了 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>
由于 TheWelcome
集成 mounted
,因此它将调用 /api/weatherforecast
终结点来检索天气预报数据。 随后,将响应设置为 forecasts
数据属性。 若要设置 server 端口,Vueclient 应用使用 PORT
环境变量。 这是通过更新 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
}
}
}
})
此外,Vite 配置中还指定了一个名为 server.proxy
的属性,用于将请求转发到“weatherapi”服务。 这是通过使用由 .NET.NET Aspire 应用主机设置的 services__weatherapi__http__0
环境变量来实现的。
模板的最终更新是 TheWelcome。vue 文件。 此文件调用 /api/WeatherForecast
终结点来检索天气预报数据,并在表中显示数据。 它包括 CSS、HTML 和 TypeScript 更新。
正在运行 Vue 应用
若要可视化 Vueclient 应用,请导航到 .NET Aspire 仪表板中的“vue”终结点。 下图描述了 Vueclient 这个应用程序:
部署注意事项
本文的示例源代码旨在在本地运行。 每个 client 应用都部署为容器镜像。 每个 client 应用的 Dockerfile 用于生成容器映像。 每个 Dockerfile 都是相同的,使用多阶段生成来创建生产就绪的容器映像。
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;"]
client 应用当前配置为作为真正的 SPA 应用运行,并且未配置为在 server端呈现的 (SSR) 模式下运行。 它们位于 nginx后面,用于为静态文件提供服务。 他们使用 default.conf.template 文件配置 nginx 以代理请求到 client 应用。
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 应用注意事项
虽然本文重点介绍 client 应用,但在某些情况下,可能需要托管 Node.jsserver 应用。 托管 Node.jsserver 应用和 SPA client 应用需要相同的规范。
.NET
.NET Aspire 应用主机需要引用 Aspire的 .Hosting.NodeJS NuGet 包,并且代码需要调用 AddNodeApp
或 AddNpmApp
。 这些 API 可用于将现有 JavaScript 应用添加到 .NET.NET Aspire 应用主机。
配置机密并将环境变量传递给基于 JavaScript 的应用时,无论它们是 client 还是 server 应用,都使用参数。 有关详细信息,请参阅 .NET.NET Aspire:外部参数 - 机密。
使用 OpenTelemetry JavaScript SDK
若要从 Node.jsserver 应用导出 OpenTelemetry 日志、跟踪和指标,请使用 OpenTelemetry JavaScript SDK。
有关使用 OpenTelemetry JavaScript SDK 的 Node.jsserver 应用的完整示例,可以参考 代码示例:.NET AspireNode.js 示例 页。 请考虑示例的 instrumentation.js 文件,其中演示如何配置 OpenTelemetry JavaScript SDK 以导出日志、跟踪和指标:
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();
}
提示
若要配置 .NET.NET Aspire 仪表板的 OTEL CORS 设置,请参阅 .NET.NET Aspire 仪表板 OTEL CORS 设置的 页。
总结
虽然本文的几个注意事项超出了本文的范围,但你已了解如何生成使用 Node.js 和 Node 包管理器(npm
)的 .NET Aspire 项目。 你还了解了如何使用 AddNpmApp API 来托管 Node.js 应用和从 包执行的应用,分别与json和 文件有关。 最后,你学习了如何使用 npm
CLI 创建 Angular、React和 Vueclient 应用,以及如何将其配置为在不同的端口上运行。