ChatGPT解决这个技术问题 Extra ChatGPT

如何在 ASP.NET Core 中使用 npm

我正在使用 npm 来管理我的 ASP.NET Core 应用程序所需的 jQuery、Bootstrap、Font Awesome 和类似的客户端库。

对我有用的方法首先是在项目中添加一个 package.json 文件,如下所示:

{
    "version": "1.0.0",
    "name": "myapp",
    "private": true,
    "devDependencies": {
  },
  "dependencies": {
    "bootstrap": "^3.3.6",
    "font-awesome": "^4.6.1",
    "jquery": "^2.2.3"
  }
}

npm 将这些包恢复到与项目目录中的 wwwroot 处于同一级别的 node_modules 文件夹中:

https://i.stack.imgur.com/5Xlw7.png

由于 ASP.NET Core 提供 wwwroot 文件夹中的静态文件,而 node_modules 不存在,因此我必须进行一些更改才能使其正常工作,第一个更改是:在我的 Startup.UseStaticFiles 之前添加 app.UseFileServer 。 cs 文件:

app.UseFileServer(new FileServerOptions()
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(Directory.GetCurrentDirectory(), @"node_modules")), 
    RequestPath = new PathString("/node_modules"),
    EnableDirectoryBrowsing = true
});

app.UseStaticFiles();

第二个,包括我在 project.json 文件中的 publishOptions 中的 node_modules :

"publishOptions": {
  "include": [
    "web.config",
    "wwwroot",
    "Views",
    "node_modules"
  ]
},

这在我的开发环境中有效,当我将它部署到我的 Azure 应用服务实例时它也有效,jquery、bootstrap 和 font-awesome 静态文件得到了很好的服务,但我不确定这个实现。

这样做的正确方法是什么?

这个解决方案是在从多个来源收集了大量信息并尝试了一些无效的信息之后出现的,而且不得不从 wwwroot 外部提供这些文件似乎有点奇怪。

任何建议将不胜感激。

此链接有一个关于 ASP.NET Core w/npm 的工作示例:ievangelistblog.wordpress.com/2016/01/13/…
我发生的一件事是使用 Bundler and Minifier - 指定源是在 wwwroot 之外,并且在构建它时将 JS 构建到 wwwroot。那是正确的方法..您不应该从 node_modules 提供内容
我强烈反对任何人静态地提供 node_modules 文件夹。 a) 这不是生态系统的设计方式 b) 这是一个安全风险,您安装的一个软件包可能会泄露敏感信息。正确的方法是设置一个构建管道 (grunt/gulp/node/webpack),将文件发布到专用于提供静态前端文件的 srcwhatever 文件夹
@PiotrKula,使用 Bundler & Minifiernode_modules 中提取文件有一个致命问题:某些 CSS 代码包含通过 CSS 中的 url 语句引用的相关文件夹。例如,Font Awesome CSS 引用了 Font Awesome 分发中其他文件夹中的资产。显示在 wwwroot 文件夹下的捆绑/缩小 CSS 文件将尝试引用 Bundler & Minifier 不知道且未复制到相对于捆绑文件的正确位置的内容。

L
Leniel Maccaferri

通过发布整个 node_modules 文件夹,您部署的文件远比生产中实际需要的要多。

相反,在构建过程中使用任务运行器来打包您需要的文件,并将它们部署到您的 wwwroot 文件夹。这也将允许您同时连接和缩小您的资产,而不必分别为每个单独的库提供服务。

然后,您还可以完全删除 FileServer 配置并改用 UseStaticFiles

目前,gulp 是首选的 VS 任务运行程序。将 gulpfile.js 添加到项目的根目录,并将其配置为在发布时处理静态文件。

例如,您可以将以下 scripts 部分添加到您的 project.json

 "scripts": {
    "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ]
  },

这将适用于以下 gulpfile(使用 yo 搭建脚手架时的默认设置):

/// <binding Clean='clean'/>
"use strict";

var gulp = require("gulp"),
    rimraf = require("rimraf"),
    concat = require("gulp-concat"),
    cssmin = require("gulp-cssmin"),
    uglify = require("gulp-uglify");

var webroot = "./wwwroot/";

var paths = {
    js: webroot + "js/**/*.js",
    minJs: webroot + "js/**/*.min.js",
    css: webroot + "css/**/*.css",
    minCss: webroot + "css/**/*.min.css",
    concatJsDest: webroot + "js/site.min.js",
    concatCssDest: webroot + "css/site.min.css"
};

gulp.task("clean:js", function (cb) {
    rimraf(paths.concatJsDest, cb);
});

gulp.task("clean:css", function (cb) {
    rimraf(paths.concatCssDest, cb);
});

gulp.task("clean", ["clean:js", "clean:css"]);

gulp.task("min:js", function () {
    return gulp.src([paths.js, "!" + paths.minJs], { base: "." })
        .pipe(concat(paths.concatJsDest))
        .pipe(uglify())
        .pipe(gulp.dest("."));
});

gulp.task("min:css", function () {
    return gulp.src([paths.css, "!" + paths.minCss])
        .pipe(concat(paths.concatCssDest))
        .pipe(cssmin())
        .pipe(gulp.dest("."));
});

gulp.task("min", ["min:js", "min:css"]);

对于这个问题的答案,我有点困惑。这几乎正是 Microsoft 在此处配置 Gulp 的内容 (docs.microsoft.com/en-us/aspnet/core/client-side/using-gulp)。但是据我所知,这不会从我的 node_modules 目录中获取内容并将其添加到“lib”或使其可用于我的任何文件中......我对此非常陌生,因此被看似难以置信的令人难以置信的困惑复杂的 Web 开发新世界...
复杂的好吧。我已经准备好完全放弃前端,只专注于 API。
这通常是正确的方法,但答案遗漏了一个关键步骤:将文件从 node_modules 文件夹复制到 wwwroot 文件夹作为 Gulp 任务。从 var nodeRoot = './node_modules/'; 开始并添加一个任务,将所需的子文件夹从 nodeRoot 复制到 webroot 的相应子文件夹中。现在没有时间详细说明,但是如果有兴趣,我可以稍后添加详细信息。
为什么没有人提出明显的问题:“我们为什么要问这个问题!”为什么我们故意将文件安装在无法使用的位置?然后,由于我们的文件不可访问,我们安装并配置了一个精心设计的实用程序,将它们复制到可以使用它们的位置。它真的很荒谬。
因为这里的工具基本上是垃圾。使用 npm 只是使用 npm,就像您使用 anything 一样。没有什么特定于 ASP.NET Core。一切都进入 node_modules,因为这就是 npm 所做的。 gulp 任务对于将事物移动到正确的位置(即您实际需要它们的位置)是必要的。我认为问题在于微软提供了与 Bower 的如此漂亮的集成,但现在 Bower 已经死了(或者至少是死了),而且微软还没有提供任何替代工具。
I
InteXX

https://i.stack.imgur.com/UgxXD.png

使用 npm 管理客户端库是一个不错的选择(与 Bower 或 NuGet 不同),您的想法是正确的 :)

将服务器端(ASP.NET Core)和客户端(例如 Angular 2、Ember、React)项目拆分到单独的文件夹中(否则您的 ASP.NET 项目可能会有很多噪音 - 客户端代码 node_modules 的单元测试文件夹,构建工件等)。与您在同一个团队中工作的前端开发人员会感谢您 :)

在解决方案级别恢复 npm 模块(类似于通过 NuGet 恢复包的方式 - 不是到项目的文件夹中),这样您也可以在单独的文件夹中进行单元和集成测试(而不是在您的内部进行客户端 JavaScript 测试) ASP.NET Core 项目)。

使用可能不需要 FileServer,拥有 StaticFiles 应该足以提供静态文件(.js、图像等)

使用 Webpack 将您的客户端代码捆绑到一个或多个块(捆绑包)中

如果您使用的是 Webpack 等模块捆绑器,则可能不需要 Gulp/Grunt

用 ES2015+ JavaScript(而不是 Bash 或 PowerShell)编写构建自动化脚本,它们将跨平台工作,并且更容易被各种 Web 开发人员访问(现在每个人都说 JavaScript)

将 wwwroot 重命名为 public,否则 Azure Web Apps 中的文件夹结构会混乱(D:\Home\site\wwwroot\wwwroot vs D:\Home\site\wwwroot\public)

仅将编译后的输出发布到 Azure Web 应用程序(永远不要将 node_modules 推送到 Web 托管服务器)。以 tools/deploy.js 为例。

访问 GitHub 上的 ASP.NET Core Starter Kit(免责声明:我是作者)


很好的答案,感谢您为社区提供入门工具包所做的工作!
今年早些时候,我成功地为英国的一个主要品牌构建了一个巨大的公共 Angular 应用程序,但我什至无法理解这个答案的大部分内容。我什至无法开始学习它,因为它到处都是。从字面上看,职业危机。
这是编写和管理客户端脚本和文件时应该做和不应该做的一个很好的总结。节省了我的时间和研究。向你致敬!
不幸的是,Visual Studio(愚蠢的恕我直言)仅根据其名称特别对待“wwwroot”目录,在解决方案资源管理器中为其提供一个特殊的“web root”图标,并将其内容默认标记为“无”而不是“内容” .如果打算将静态服务的文件放在那里,并且您使用的是 Visual Studio,则可能应该将名称保留为“wwwroot”。我同意这是一个坏名字。
P
Piotr Kula

Bundler and Minifier 安装到 Visual Studio 扩展中

然后创建一个 bundleconfig.json 并输入以下内容:

// Configure bundling and minification for the project.
// More info at https://go.microsoft.com/fwlink/?LinkId=808241
[
 {
    "outputFileName": "wwwroot/js/jquery.min.js",
    "inputFiles": [
      "node_modules/jquery/dist/jquery.js"
    ],
    // Optionally specify minification options
    "minify": {
      "enabled": true,
      "renameLocals": false
    },
    // Optionally generate .map file
    "sourceMap": false
  }
]

因此捆绑器和压缩器(基于 gulp)可以访问源文件(应从 Visual Studio 中排除,也应从 GIT 中排除)并按指定将它们放入 wwwroot

每次保存时只有副作用会运行它(但您可以将其设置为手动运行)


在看到 Bower 死了并且我不能再更新 Bootstrap 而不切换到 NPM 之后,这似乎是我最喜欢的方法。与这个已经在最新 MVC 项目模板中的简单解决方案相比,Gulp 或 Webpack 似乎有点过头了。感谢你的分享!
此处如何处理 css 中引用的图像?我面临的图像仍然在 node_modules 文件夹中的问题,因为 css 和 js 被移动到 www。知道如何解决这个问题吗?
这是与 IDE 无关的吗?如果您的一些团队正在使用 VS Code,这将如何工作,以及这如何在 CD 构建管道中发挥作用?
当您安装 Bundler 和 Minifier NuGet 包时,文档说它会注入在构建和清理时运行的构建目标。我想一旦到位,无论使用哪个 IDE,它都会正常工作,对吧?查看更多:docs.microsoft.com/en-gb/aspnet/core/client-side/…
捆绑器仅对在开发环境之外指定这些脚本有用。从我的 _Layout 页面我仍然需要手动引用我需要的 JS 和 CSS 文件,但是 node_modules 文件夹在网站之外......所以我认为这不能正确解决问题,你仍然需要一个 Gulp 脚本来复制将必要的文件转移到我的 wwwroot 文件夹中。
C
Community

我给你两个答案。 npm 与其他工具相结合是强大的,但需要一些工作来设置。如果您只想下载一些库,则可能需要使用库管理器(在 Visual Studio 15.8 中发布)。

NPM(高级)

首先在项目的根目录中添加 package.json。添加以下内容:

{
  "version": "1.0.0",
  "name": "asp.net",
  "private": true,
  "devDependencies": {
    "gulp": "3.9.1",
    "del": "3.0.0"
  },
  "dependencies": {
    "jquery": "3.3.1",
    "jquery-validation": "1.17.0",
    "jquery-validation-unobtrusive": "3.2.10",
    "bootstrap": "3.3.7"
  }
}

这将使 NPM 将新 asp.net 核心项目中使用的 Bootstrap、JQuery 和其他库下载到名为 node_modules 的文件夹中。下一步是将文件复制到适当的位置。为此,我们将使用 gulp,它也是由 NPM 下载的。然后在项目的根目录中添加一个名为 gulpfile.js 的新文件。添加以下内容:

/// <binding AfterBuild='default' Clean='clean' />
/*
This file is the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007
*/

var gulp = require('gulp');
var del = require('del');

var nodeRoot = './node_modules/';
var targetPath = './wwwroot/lib/';

gulp.task('clean', function () {
    return del([targetPath + '/**/*']);
});

gulp.task('default', function () {
    gulp.src(nodeRoot + "bootstrap/dist/js/*").pipe(gulp.dest(targetPath + "/bootstrap/dist/js"));
    gulp.src(nodeRoot + "bootstrap/dist/css/*").pipe(gulp.dest(targetPath + "/bootstrap/dist/css"));
    gulp.src(nodeRoot + "bootstrap/dist/fonts/*").pipe(gulp.dest(targetPath + "/bootstrap/dist/fonts"));

    gulp.src(nodeRoot + "jquery/dist/jquery.js").pipe(gulp.dest(targetPath + "/jquery/dist"));
    gulp.src(nodeRoot + "jquery/dist/jquery.min.js").pipe(gulp.dest(targetPath + "/jquery/dist"));
    gulp.src(nodeRoot + "jquery/dist/jquery.min.map").pipe(gulp.dest(targetPath + "/jquery/dist"));

    gulp.src(nodeRoot + "jquery-validation/dist/*.js").pipe(gulp.dest(targetPath + "/jquery-validation/dist"));

    gulp.src(nodeRoot + "jquery-validation-unobtrusive/dist/*.js").pipe(gulp.dest(targetPath + "/jquery-validation-unobtrusive"));
});

此文件包含在构建和清理项目时执行的 JavaScript 代码。它会将所有必要的文件复制到 lib2(不是 lib - 您可以轻松更改它)。我使用了与新项目相同的结构,但很容易将文件更改到不同的位置。如果您移动文件,请确保您还更新了 _Layout.cshtml。请注意,清理项目时将删除 lib2 目录中的所有文件。

如果您右键单击 gulpfile.js,您可以选择 Task Runner Explorer。从这里你可以手动运行 gulp 来复制或清理文件。

Gulp 还可以用于其他任务,例如缩小 JavaScript 和 CSS 文件:

https://docs.microsoft.com/en-us/aspnet/core/client-side/using-gulp?view=aspnetcore-2.1

库管理器(简单)

右键单击您的项目并选择管理客户端库。文件 libman.json 现在已打开。在此文件中,您指定要使用的库和文件以及它们应在本地存储的位置。真的很简单!以下文件复制了创建新 ASP.NET Core 2.1 项目时使用的默认库:

{
  "version": "1.0",
  "defaultProvider": "cdnjs",
  "libraries": [
    {
      "library": "jquery@3.3.1",
      "files": [ "jquery.js", "jquery.min.map", "jquery.min.js" ],
      "destination": "wwwroot/lib/jquery/dist/"
    },
    {
      "library": "jquery-validate@1.17.0",
      "files": [ "additional-methods.js", "additional-methods.min.js", "jquery.validate.js", "jquery.validate.min.js" ],
      "destination": "wwwroot/lib/jquery-validation/dist/"
    },
    {
      "library": "jquery-validation-unobtrusive@3.2.10",
      "files": [ "jquery.validate.unobtrusive.js", "jquery.validate.unobtrusive.min.js" ],
      "destination": "wwwroot/lib/jquery-validation-unobtrusive/"
    },
    {
      "library": "twitter-bootstrap@3.3.7",
      "files": [
        "css/bootstrap.css",
        "css/bootstrap.css.map",
        "css/bootstrap.min.css",
        "css/bootstrap.min.css.map",
        "css/bootstrap-theme.css",
        "css/bootstrap-theme.css.map",
        "css/bootstrap-theme.min.css",
        "css/bootstrap-theme.min.css.map",
        "fonts/glyphicons-halflings-regular.eot",
        "fonts/glyphicons-halflings-regular.svg",
        "fonts/glyphicons-halflings-regular.ttf",
        "fonts/glyphicons-halflings-regular.woff",
        "fonts/glyphicons-halflings-regular.woff2",
        "js/bootstrap.js",
        "js/bootstrap.min.js",
        "js/npm.js"
      ],
      "destination": "wwwroot/lib/bootstrap/dist"
    },
    {
      "library": "list.js@1.5.0",
      "files": [ "list.js", "list.min.js" ],
      "destination": "wwwroot/lib/listjs"
    }
  ]
}

如果您移动文件,请确保您还更新了 _Layout.cshtml。


图书馆经理——没听说过,但正是我需要的!这应该是正确的答案。
为了避免 gulp 错误,我必须将文件 gulpfile.js 中默认任务的第一行更改为 gulp.task('default', function (done) {,然后在该函数的最后一行添加以下内容:done(); 否则我会收到错误消息 {4 }
C
Community

除了尝试提供节点模块文件夹之外,您还可以使用 Gulp 将您需要的内容复制到 wwwroot。

https://docs.asp.net/en/latest/client-side/using-gulp.html

这也可能有帮助

Visual Studio 2015 ASP.NET 5, Gulp task not copying files from node_modules


我真的很喜欢第二个链接,似乎有点熟悉。 ;)
当您将 ASP.NET Core Web 应用程序源文件与 npm 模块和客户端代码构建输出混合时,这不是很方便。这就是 ASP.NET 团队从默认的 ASP.NET MVC 项目模板中删除 Gulp、package.json 的原因。
我不知道。当我三月份在 VS Live 时,他们都在谈论它,但从那以后它发生了很大变化。
C
Community

这样做的正确方法是什么?

有很多“正确”的方法,您只需决定哪一种最适合您的需求。您似乎误解了如何使用 node_modules...

如果您熟悉 NuGet,您应该将 npm 视为它的客户端对应物。其中 node_modules 目录类似于 NuGetbin 目录。这个想法是这个目录只是一个存储包的常用位置,在我看来,最好在你需要的包上加上一个dependency,就像你在 package.json 中所做的那样。然后使用像 Gulp 这样的任务运行器将您需要的文件复制到所需的 wwwroot 位置。

我在一月份写了一篇关于此的blog post,其中详细介绍了 npmGulp 以及今天仍然相关的一大堆其他细节。此外,有人提请注意我提出的 SO 问题,并最终回答了我自己 here,这可能会有所帮助。

我创建了一个以 gulpfile.js 为例的 Gist

在您的 Startup.cs 中,使用静态文件仍然很重要:

app.UseStaticFiles();

这将确保您的应用程序可以访问它需要的内容。


“我在一月份写了一篇关于这个的博客文章,详细介绍了 npm、Gulp 和一大堆今天仍然相关的其他细节。”事实上,从 1 月到 6 月,你必须提到仍然是相关的,这正是我费心去学习任何这些不靠谱的东西的问题。我已经有太多要学的东西了,不能把时间浪费在时尚上。大卫不是你的错,你很有帮助,但我不喜欢这个短暂的新世界。
M
Mariusz Bialobrzeski

更简单的方法是使用 OdeToCode.UseNodeModules Nuget 包。我刚刚使用 .Net Core 3.0 对其进行了测试。您需要做的就是将包添加到解决方案中并在 Startup 类的 Configure 方法中引用它:

app.UseNodeModules();

我是从 Shawn Wildermuth 的出色 Building a Web App with ASP.NET Core, MVC, Entity Framework Core, Bootstrap, and Angular Pluralsight 课程中了解到的。


以及如何添加 npm 包?
有几种方法可以将 npm 包添加到您的项目中。我更喜欢在依赖项节点下的 package.json 文件中键入它们,如下所述:stackoverflow.com/a/49264424/5301317
@MariuszBialobrzeski 感谢分享。这是一个巧妙的解决方案。
@MariuszBialobrzeski 您是否需要做任何其他事情才能在 DevOps 管道中部署来自 node_modules 的静态内容?还是您检查了 node_modules 文件夹?
@Sau001 不幸的是,我从来没有机会使用 DevOps 管道。 node_modules 文件夹往往会变得非常大,所以如果可能的话,我肯定会避免检查它。
C
Community

Shawn Wildermuth 在这里有一个很好的指南:https://wildermuth.com/2017/11/19/ASP-NET-Core-2-0-and-the-End-of-Bower

文章链接到 GitHub 上的 gulpfile,他在其中实施了文章中的策略。您可以将大部分 gulpfile 内容复制并粘贴到您的文件中,但请务必在 devDependencies 下的 package.json 中添加适当的包: gulp gulp-uglify gulp-concat rimraf merge-stream


P
Peter Húbek

我找到了一种更好的方法来使用 NPM Gulp/Grunt 任务运行器在我的项目中管理 JS 包。我不喜欢有一个 NPM 和另一层 javascript 库来处理“自动化”,我的第一个要求是简单地运行 npm 更新,而无需担心是否需要运行 gulp 的东西,如果它成功复制了所有内容,反之亦然。

NPM方式:

JS minifier 已经捆绑在 ASP.net 核心中,寻找 bundleconfig.json 所以这对我来说不是问题(不是编译自定义的东西) NPM 的好处是它有一个很好的文件结构,所以我总能找到node_modules/module/dist 下依赖项的预编译/缩小版本我正在使用 NPM node_modules/.hooks/{eventname} 脚本,该脚本正在处理 Project/wwwroot/lib/module 的复制/更新/删除/dist/.js 文件,你可以在这里找到文档 https://docs.npmjs.com/misc/scripts (我会更新我正在使用的脚本到 git 一旦它会更加优美)我不不需要额外的任务运行器(我不喜欢的 .js 工具)来保持我的项目简洁明了。

蟒蛇方式:

https://pypi.python.org/pyp... 但在这种情况下,您需要手动维护源代码


b
b01

请原谅这篇文章的长度。

这是一个使用 ASP.NET Core 2.5 版的工作示例。

值得注意的是,project.json 已过时 (see here),取而代之的是 .csproj.csproj 的问题。文件是大量的功能,事实上它的文档没有中心位置 (see here)。

还有一件事,这个例子是在 Docker Linux (alpine 3.9) 容器中运行 ASP.NET core;所以路径将反映这一点。它还使用 gulp ^4.0。但是,经过一些修改,它应该可以与旧版本的 ASP.NET Core、Gulp、NodeJS 一起使用,并且也可以在没有 Docker 的情况下使用。

但这里有一个答案:

gulpfile.js see the real working exmple here

// ROOT and OUT_DIR are defined in the file above. The OUT_DIR value comes from .NET Core when ASP.net us built.
const paths = {
    styles: {
        src: `${ROOT}/scss/**/*.scss`,
        dest: `${OUT_DIR}/css`
    },
    bootstrap: {
        src: [
            `${ROOT}/node_modules/bootstrap/dist/css/bootstrap.min.css`,
            `${ROOT}/node_modules/startbootstrap-creative/css/creative.min.css`
        ],
        dest: `${OUT_DIR}/css`
    },
    fonts: {// enter correct paths for font-awsome here.
        src: [
            `${ROOT}/node_modules/fontawesome/...`,
        ],
        dest: `${OUT_DIR}/fonts`
    },
    js: {
        src: `${ROOT}/js/**/*.js`,
        dest: `${OUT_DIR}/js`
    },
    vendorJs: {
        src: [
            `${ROOT}/node_modules/jquery/dist/jquery.min.js`
            `${ROOT}/node_modules/bootstrap/dist/js/bootstrap.min.js`
        ],
        dest: `${OUT_DIR}/js`
    }
};

// Copy files from node_modules folder to the OUT_DIR.
let fonts = () => {
    return gulp
        .src(paths.styles.src)
        .pipe(gulp.dest(paths.styles.dest));
};

// This compiles all the vendor JS files into one, jsut remove the concat to keep them seperate.
let vendorJs = () => {
    return gulp
        .src(paths.vendorJs.src)
        .pipe(concat('vendor.js'))
        .pipe(gulp.dest(paths.vendorJs.dest));
}

// Build vendorJs before my other files, then build all other files in parallel to save time.
let build = gulp.series(vendorJs, gulp.parallel(js, styles, bootstrap));

module.exports = {// Only add what we intend to use externally.
    default: build,
    watch
};

.csproj 文件中添加 Target。请注意,如果我们利用 dotnet run watch 命令,我们还添加了一个 Watch 来观察和排除。

app.csprod

  <ItemGroup>
    <Watch Include="gulpfile.js;js/**/*.js;scss/**/*.scss" Exclude="node_modules/**/*;bin/**/*;obj/**/*" />
  </ItemGroup>

  <Target Name="BuildFrontend" BeforeTargets="Build">
    <Exec Command="yarn install" />
    <Exec Command="yarn run build -o $(OutputPath)" />
  </Target>

现在,当 dotnet run build 运行时,它还将安装和构建节点模块。