首页 文章

如何将 npm 与 ASP.NET Core 一起使用

提问于
浏览
98

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

在此输入图像描述

由于 ASP.NET Core 提供来自 wwwroot 文件夹的静态文件,并且 node_modules 不存在,我不得不进行一些更改才能使其工作,第一个:在 app.UseStaticFiles 文件中 app.UseStaticFiles 之前添加 app.UseFileServer:

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 App Service 实例时,它也可以工作,jquery,bootstrap 和 font-awesome 静态文件得到很好的服务,但我不确定这个实现。

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

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

任何建议将不胜感激。

9 回答

  • 7

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

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

    这也可能有所帮助

    Visual Studio 2015 ASP.NET 5,Gulp 任务不从 node_modules 复制文件

  • 36

    通过发布整个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"]);
    
  • 40

    在此输入图像描述

    • 使用npm来管理 client-side 库是一个不错的选择(与 Bower 或 NuGet 相反),你正在思考正确的方向:)

    • 将 server-side(ASP.NET 核心)和 client-side(e.g. Angular 2,Ember,React)项目拆分为单独的文件夹(否则你的 ASP.NET 项目可能会有很多噪音 - 对 client-side 代码进行单元测试,node_modules 文件夹,构建工件 etc.)。Front-end 开发人员工作在同一个团队中,你会感谢你:)

    • 在解决方案级别恢复 npm 模块(类似于如何通过 NuGet 恢复软件包 - 而不是恢复到项目的文件夹中),这样您就可以在单独的文件夹中进行单元和集成测试(而不是在 ASP.NET 核心内部进行 client-side JavaScript 测试)项目)。

    • 使用可能不需要FileServerStaticFiles应该足以提供静态文件(.js,images etc.)

    • 使用 Webpack 将 client-side 代码捆绑到一个或多个块(捆绑包)中

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

    • 在 ES2015 JavaScript(而不是 Bash 或 PowerShell)中编写构建自动化脚本,它们将工作 cross-platform 并且更容易被各种 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 核心入门套件(免责声明:我是作者)

  • 24

    Bundler 和 Minifier安装到 Visual Studio Extensions 中

    然后你创建一个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 中

    每次保存时只有副作用会运行(或者您可以设置或手动运行)

  • 15

    我给你两个答案。 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-directory 中的所有文件。

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

    Gulp 对于缩小 JavaScript 和 CSS-files 等其他任务也很有用:

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

    图书馆经理(简单)

    右键单击您的项目并选择Manage client side-libraries。文件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**。

  • 5

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

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

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

    我在 1 月份写了一篇关于这个的详细信息,详细说明npmGulp和其他一些今天仍然相关的细节。另外,有人提醒我注意我提出的问题并最终回答了自己这里,这可能会有所帮助。

    我创建了一个要旨,以gulpfile.js为例。

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

    app.UseStaticFiles();
    

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

  • 1

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

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

  • 1

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

    NPM 方式:

    • JS minifier 已经捆绑在 ASP.net 核心中,寻找 bundleconfig.json 所以这对我来说不是问题(不编译自定义的东西)
    • NPM 的好处是具有良好的文件结构,所以我总能在 node_modules/module/dist 下找到 pre-compiled/minified 版本的依赖项

    • 我正在使用 NPM node_modules/.hooks/ {。处理 Project/wwwroot/lib/module/dist/.js 文件的 copy/update/delete 的脚本,你可以在这里找到文档https://docs.npmjs.com/misc/scripts(我将更新我用来 git 的脚本,一旦它更加精致)我不需要额外的任务运行(.js 我不喜欢的工具)是什么让我的项目干净简单。

    python 的方式:

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

  • 0

    请原谅这篇文章的篇幅。

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

    值得注意的是,project.json已经过时(看这里),有利于**.csproj**。 .csproj的问题。文件是大量的功能,事实上它的文档没有中心位置(看这里)。

    还有一件事,这个例子是在 Docker Linux(alpine 3.9)容器中运行 ASP.NET core;所以路径会反映出来。它还使用 gulp ^ 4.0. 但是,通过一些修改,它应该适用于旧版本的 ASP.NET Core,Gulp,NodeJS,以及没有 Docker。

    但这是一个答案:

    gulpfile.js 在这里看到真正有效的工作

    // 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命令,我们还添加了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运行时,它还将安装和构建节点模块。

相关问题