如何在 ASP.NET 内核中使用 npm

我使用 npm 来管理我的 ASP.NET 核心应用程序所需的 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 将这些包恢复到 node _ module 文件夹中,该文件夹与项目目录中的 wwwroot 处于同一级别:

enter image description here

由于 ASP.NET Core 提供来自 wwwroot 文件夹的静态文件,而 node _ module 不在这个文件夹中,所以我必须做一些修改才能使其正常工作,第一个修改是: 添加应用程序。UseFileServer 就在应用程序之前。我的 Startup.cs 文件中的 UseStaticFiles:

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 _ module:

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

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

做这件事的正确方法是什么?

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

如有任何建议,我们将不胜感激。

138920 次浏览

您也可以使用 Gulp 将需要的内容复制到 wwwroot,而不是尝试提供节点模块文件夹。

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

这个可能也有帮助

Visual Studio 2015 ASP.NET 5,Gulp 任务没有从 node _ module 复制文件

enter image description here

  • 使用 npm管理客户端库是一个很好的选择(相对于 Bower 或 NuGet) ,您的思路是正确的:)
  • 将服务器端(ASP.NET 核心)和客户端(如 Angular 2,Ember,React)项目拆分成单独的文件夹(否则你的 ASP.NET 项目可能会有很多客户端代码、 node _ module 文件夹、构建工件等的噪声单元测试)。与您在同一个团队中工作的前端开发人员会为此感谢您:)
  • 在解决方案级别上恢复 npm 模块(类似于你如何通过 NuGet 恢复软件包——而不是到项目的文件夹中) ,这样你也可以在一个单独的文件夹中进行单元测试和集成测试(而不是在你的 ASP.NET 核心项目中进行客户端 JavaScript 测试)。
  • 使用可能不需要 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 Apps (永远不要将 node_modules推送到 Web 托管服务器)。以 tools/deploy.js为例。

访问 GitHub 上的 ASP.NET 核心入门工具包(免责声明: 我是作者)

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

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

然后您还可以完全删除 FileServer配置并依赖于 UseStaticFiles

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

例如,可以在 project.json中添加以下 scripts部分:

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

做这件事的正确方法是什么?

有很多“正确”的方法,你只需要决定哪一个最适合你的需要。看起来你好像误解了如何使用 node_modules..。

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

我在一月份写了一篇关于这方面的 博客文章文章,详细介绍了 Npm咕噜以及其他一大堆今天仍然相关的细节。此外,有人呼吁注意我的 SO 问题,我问,并最终回答自己 给你,这可能是有帮助的。

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

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

app.UseStaticFiles();

这将确保您的应用程序能够访问它所需要的内容。

打包机和缩小机安装到 VisualStudio 扩展中

然后创建一个 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
}
]

因此,bundler 和 minifier (基于 Gulp)可以访问源文件(应该从 Visual Studio 中排除,也应该从 GIT 中排除) ,并将它们放入指定的 wwwroot 中

只有副作用每次你保存它将运行此(但你可以设置为手动运行它)

Shawn Wildermuth has a nice guide here: https://wildermuth.com/2017/11/19/ASP-NET-Core-2-0-and-the-End-of-Bower

本文链接到 GitHub 上的 Gulpfile,在那里他实现了本文中的策略。你可以直接复制粘贴 Gulpfile 的大部分内容,但一定要在 devDependency 下的 package.json 中添加适当的包: 吞下去 狼吞虎咽 狼吞虎咽 Rimraf 合并流

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

NPM 方式:

  • JS 小型化程序已经绑定在 ASP.net 核心中,请查找 bundleconfig.json,所以这对我来说不是问题(不是编译) 一些定制的东西)
  • NPM 的好处是有一个好的文件结构,这样我就可以总是找到依赖项的预编译/缩小版本 在 node _ module/module/dist 下
  • 我正在使用 NPM node _ module/. hooks/{ eventname }脚本,该脚本处理 Project/wwwroot/lib/module/dist/< em > . js 文件,您可以找到 文档在这里 https://docs.npmjs.com/misc/scripts(我将更新我正在使用的脚本,一旦它将更加抛光)我不需要 额外的任务运行器(我不喜欢的 . js 工具)使我的项目保持清洁和简单。

蟒蛇之道:

Https://pypi.python.org/pyp ... ... 但在这种情况下,你需要保持 手动接收信号

我给你两个答案。Npm与其他工具的结合是强大的,但需要一些工作来设置。如果您只是想下载一些库,那么可能需要改用 图书馆经理(在 Visual Studio 15.8中发布)。

NPM (高级)

首先在项目的根目录中添加 包裹 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 _ module 的文件夹中。下一步是将文件复制到适当的位置。为此,我们将使用 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(而不是自由主义——你可以很容易地改变这一点)。我在新项目中使用了相同的结构,但是很容易将文件更改到不同的位置。如果移动了文件,请确保也更新了 _ Layout.cshtml。请注意,在清理项目时,lib2-目录中的所有文件都将被删除。

如果右键单击 Gulpfile.js,可以选择 任务运行程序资源管理器。从这里您可以手动运行 Gulp 来复制或清除文件。

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

Https://learn.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

请原谅这篇文章的长度。

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

值得注意的是 Project Json已经过时了(看这里) 。 csproj.file 的一个问题是大量的特性和 其文档没有中心位置(看这里)。

还有一件事,这个例子是在 Docker Linux (alpine 3.9)容器中运行 ASP.NET 核心; 所以路径会反映这一点。它也使用了 Gulp ^ 4.0。然而,对于一些 修改后,它应该可以与旧版本的 ASP.NET 核心,Gulp, NodeJS,也没有 Docker。

但答案是:

看看这里真正的工作示例

// 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文件中添加一个 目标。注意,我们还添加了一个 看好了来观察 并排除如果我们利用 dotnet run 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时,它还将安装和构建节点模块。

更简单的方法是使用 使用节点模块 Nuget 软件包。我刚测试过。Net Core 3.0.您所需要做的就是将包添加到解决方案中,并在 Startup 类的 Configure 方法中引用它:

app.UseNodeModules();

我是从 Shawn Wildermuth 的优秀的 使用 ASP.NET 内核、 MVC、实体框架内核、 Bootstrap 和角度构建 Web 应用程序 Pluralsight 课程中学到的。