How to use npm with ASP.NET Core

前端 未结 10 2003
孤街浪徒
孤街浪徒 2020-11-29 15:05

I\'m using npm to manage the jQuery, Bootstrap, Font Awesome and similar client libraries I need for my ASP.NET Core application.

The approach that worked for me sta

相关标签:
10条回答
  • 2020-11-29 15:59

    By publishing your whole node_modules folder you are deploying far more files than you will actually need in production.

    Instead, use a task runner as part of your build process to package up those files you require, and deploy them to your wwwroot folder. This will also allow you to concat and minify your assets at the same time, rather than having to serve each individual library separately.

    You can then also completely remove the FileServer configuration and rely on UseStaticFiles instead.

    Currently, gulp is the VS task runner of choice. Add a gulpfile.js to the root of your project, and configure it to process your static files on publish.

    For example, you can add the following scripts section to your project.json:

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

    Which would work with the following gulpfile (the default when scaffolding with 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"]);
    
    0 讨论(0)
  • 2020-11-29 16:06

    • Using npm for managing client-side libraries is a good choice (as opposed to Bower or NuGet), you're thinking in the right direction :)
    • Split server-side (ASP.NET Core) and client-side (e.g. Angular 2, Ember, React) projects into separate folders (otherwise your ASP.NET project may have lots of noise - unit tests for the client-side code, node_modules folder, build artifacts, etc.). Front-end developers working in the same team with you will thank you for that :)
    • Restore npm modules at the solution level (similarly how you restore packages via NuGet - not into the project's folder), this way you can have unit and integration tests in a separate folder as well (as opposed to having client-side JavaScript tests inside your ASP.NET Core project).
    • Use might not need FileServer, having StaticFiles should suffice for serving static files (.js, images, etc.)
    • Use Webpack to bundle your client-side code into one or more chunks (bundles)
    • You might not need Gulp/Grunt if you're using a module bundler such as Webpack
    • Write build automation scripts in ES2015+ JavaScript (as opposed to Bash or PowerShell), they will work cross-platform and be more accessible to a variety of web developers (everyone speaks JavaScript nowadays)
    • Rename wwwroot to public, otherwise the folder structure in Azure Web Apps will be confusing (D:\Home\site\wwwroot\wwwroot vs D:\Home\site\wwwroot\public)
    • Publish only the compiled output to Azure Web Apps (you should never push node_modules to a web hosting server). See tools/deploy.js as an example.

    Visit ASP.NET Core Starter Kit on GitHub (disclaimer: I'm the author)

    0 讨论(0)
  • 2020-11-29 16:11

    What is the right approach for doing this?

    There are a lot of "right" approaches, you just have decide which one best suites your needs. It appears as though you're misunderstanding how to use node_modules...

    If you're familiar with NuGet you should think of npm as its client-side counterpart. Where the node_modules directory is like the bin directory for NuGet. The idea is that this directory is just a common location for storing packages, in my opinion it is better to take a dependency on the packages you need as you have done in the package.json. Then use a task runner like Gulp for example to copy the files you need into your desired wwwroot location.

    I wrote a blog post about this back in January that details npm, Gulp and a whole bunch of other details that are still relevant today. Additionally, someone called attention to my SO question I asked and ultimately answered myself here, which is probably helpful.

    I created a Gist that shows the gulpfile.js as an example.

    In your Startup.cs it is still important to use static files:

    app.UseStaticFiles();
    

    This will ensure that your application can access what it needs.

    0 讨论(0)
  • 2020-11-29 16:11

    Please excuse the length of this post.

    This is a working example using ASP.NET Core version 2.5.

    Something of note is that the project.json is obsolete (see here) in favor of .csproj. An issue with .csproj. file is the large amount of features and the fact there is no central location for its documentation (see here).

    One more thing, this example is running ASP.NET core in a Docker Linux (alpine 3.9) container; so the paths will reflect that. It also uses gulp ^4.0. However, with some modification, it should work with older versions of ASP.NET Core, Gulp, NodeJS, and also without Docker.

    But here's an answer:

    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
    };
    
    

    Add a Target in .csproj file. Notice we also added a Watch to watch and exclude if we take advantage of dotnet run watch command.

    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>
    

    Now when dotnet run build is run it will also install and build node modules.

    0 讨论(0)
提交回复
热议问题