C# 如何将npm与ASP.NET核心一起使用

C# 如何将npm与ASP.NET核心一起使用,c#,asp.net-mvc,npm,gulp,asp.net-core,C#,Asp.net Mvc,Npm,Gulp,Asp.net Core,我正在使用npm来管理我的ASP.NET核心应用程序所需的jQuery、Bootstrap、Font Awesome和类似的客户端库 我采用的方法是向项目中添加一个package.json文件,如下所示: { "version": "1.0.0", "name": "myapp", "private": true, "devDependencies": { }, "dependencies": { "bootstrap": "^3.3.6",

我正在使用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将这些包还原到与项目目录中的wwwroot处于同一级别的node_modules文件夹中:

由于ASP.NET Core为wwwroot文件夹中的静态文件提供服务,而node_模块不在其中,因此我必须进行一些更改,第一个更改是:将app.UseFileServer添加到Startup.cs文件中app.usesticfiles之前:

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

app.UseStaticFiles();
第二个,包括project.json文件中my publishOptions中的node_模块:

"publishOptions": {
  "include": [
    "web.config",
    "wwwroot",
    "Views",
    "node_modules"
  ]
},
这在我的开发环境中有效,在我将其部署到Azure应用程序服务实例时也有效,jquery、bootstrap和font-awesome静态文件得到了很好的服务,但我不确定这个实现

这样做的正确方法是什么

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


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

您也可以使用Gulp将所需内容复制到wwwroot,而不是尝试为node modules文件夹提供服务

这可能也有帮助

  • 使用
    npm
    管理客户端库是一个不错的选择(与Bower或NuGet相反),您的思路是正确的:)
  • 将服务器端(ASP.NET Core)和客户端(例如Angular 2、Ember、React)项目拆分为单独的文件夹(否则,您的ASP.NET项目可能会有大量针对客户端代码、节点模块文件夹、构建工件等的噪音单元测试)。与您在同一团队中工作的前端开发人员将为此感谢您:)
  • 在解决方案级别恢复npm模块(类似于通过NuGet恢复包的方式,而不是将包恢复到项目的文件夹中),这样您也可以在单独的文件夹中进行单元和集成测试(而不是在ASP.NET核心项目中进行客户端JavaScript测试)
  • 使用可能不需要
    文件服务器
    ,拥有
    静态文件
    就足以提供静态文件(.js、图像等)
  • 使用Webpack将客户端代码捆绑成一个或多个块(捆绑包)
  • 如果您使用的是模块绑定器,如Webpack
  • 使用ES2015+JavaScript编写构建自动化脚本(与Bash或PowerShell相反),它们可以跨平台工作,并且更容易被各种web开发人员访问(现在每个人都说JavaScript)
  • wwwroot
    重命名为
    public
    ,否则Azure Web应用程序中的文件夹结构将令人困惑(
    D:\Home\site\wwwroot\wwwroot
    vs
    D:\Home\site\wwwroot\public
  • 仅将编译后的输出发布到Azure Web Apps(您不应将
    node\u模块
    推送到Web托管服务器)。请看一个例子

访问GitHub上的(免责声明:我是作者)

发布整个
节点模块
文件夹,您部署的文件远远超过了生产中实际需要的文件

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

然后,您还可以完全删除
文件服务器
配置,改用
UseStaticFiles

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

例如,您可以将以下
脚本
部分添加到
项目.json

 "scripts": {
    "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ]
  },
这将与以下gulpfile一起使用(使用
yo
搭建脚手架时的默认设置):

//
“严格使用”;
var gulp=需要(“gulp”),
rimraf=要求(“rimraf”),
concat=需要(“吞咽concat”),
cssmin=需要(“吞咽cssmin”),
丑陋=需要(“吞咽丑陋”);
var webroot=“./wwwroot/”;
变量路径={
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”
};
任务(“clean:js”,函数(cb){
rimraf(path.concatJsDest,cb);
});
任务(“清理:css”,函数(cb){
rimraf(paths.concatCssDest,cb);
});
任务(“clean”,“clean:js”,“clean:css”);
任务(“min:js”,函数(){
return gulp.src([path.js,“!”+path.minJs],{base:“.”)
.pipe(concat(path.concatJsDest))
.管道(丑()
.管道(大口目的地(“.”);
});
任务(“min:css”,函数(){
return gulp.src([path.css,!”+path.minCss])
.pipe(concat(path.concatCssDest))
.pipe(cssmin())
.管道(大口目的地(“.”);
});
吞咽任务(“min”,“min:js”,“min:css”);
这样做的正确方法是什么

有很多“正确”的方法,你只需要决定哪一种最适合你的需要。似乎您误解了如何使用
node\u模块

如果您熟悉NuGet,则应将npm视为其客户端对应项。其中,
node\u modules
目录类似于NuGet
bin
目录。这个目录只是存储包的一个常用位置,我认为最好像在
package.json
中那样对所需的包进行
依赖。然后使用
/// <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"]);
app.UseStaticFiles();
// 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
  }
]
{
  "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"
  }
}
/// <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"));
});
{
  "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"
    }
  ]
}
app.UseNodeModules();