How to use npm with ASP.NET Core
Asked Answered
Y

10

159

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 started by adding a package.json file to the project, that looks like this:

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

npm restores these packages into the node_modules folder which is on the same level as wwwroot in the project directory:

enter image description here

As ASP.NET Core serves the static files from the wwwroot folder, and node_modules is not there, I had to make a couple of changes to make this work, the first one: adding app.UseFileServer right before app.UseStaticFiles in my Startup.cs file:

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

app.UseStaticFiles();

and the second one, including node_modules in my publishOptions in the project.json file:

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

This works in my development environment and it also works when I deploy it to my Azure App Service instance, the jquery, bootstrap and font-awesome static files get served well, but I'm not sure about this implementation.

What is the right approach for doing this?

This solution came after collecting lots of bits of info from several sources and trying some that didn't work, and it seems a bit odd having to serve these files from outside wwwroot.

Any advice will be greatly appreciated.

Yesman answered 21/6, 2016 at 4:19 Comment(8)
May be useful link: blog.nbellocam.me/2016/03/14/asp-net-core-and-angular-2Goar
This link has a working example on ASP.NET Core w/ npm: ievangelistblog.wordpress.com/2016/01/13/…Hand
One thing that occured to me is to use the Bundler and Minifier - Specify the source is Outside wwwroot and when you build it builds the JS in to wwwroot. That is the proper way.. You should not be serving content from node_modulesSwum
I would highly discourage anyone from statically serving the node_modules folder. a) that's not how the eco-system is designed b) it's a security risk, one of your installed packages might leak sensitive information. The proper way is to set-up a building pipeline (grunt/gulp/node/webpack) that publishes files to a src or whatever folder dedicated to serving static front-end filesDiplomatics
@PiotrKula, using Bundler & Minifier to pull files out of node_modules has one fatal problem: Some CSS code contains relative folder references via url statements in the CSS. For example, the Font Awesome CSS has references to assets in other folders in the Font Awesome distribution. The bundled/minified CSS file that shows up under your wwwroot folder will try to reference stuff that Bundler & Minifier didn't know about and didn't copy to the correct place relative to the bundled file.Guzman
Yes there is that problem.. but really I think that the CSS should be relative to its own self.. so if it gets copied over to where ever in the some folder structure.. it shouldn't matter. So unfortunately packages like that I just manually manage - But I think that Bundler and Minifier is not recommended any more - Rather use like NPM's WebPack or the other ones which do a great jobSwum
@PiotrKula, LOL, just what I need... another client-side technology to figure out. HELP! Have you (or anyone reading this) seen something that can help me figure out how to use WebPack to bridge the gap between npm (the node_modules folder) and my ASP.NET Core web app? Somehow I need to fetch the modules I've explicitly listed in package.json and all of their JS dependencies and put that bundled file somewhere under the wwwroot folder. I really don't want to have to stare at the dependencies produced by "npm list" and add a zillion lines to bundleconfig.json.Guzman
Roughly every 6 months I decide I'm going to start using npm (or, historically, bower) in my web app projects, then I spend an hour or two reading up on how I might do so in a way that would work nicely and tidily with my projects in Visual Studio. After reading about config files and scripts to move files around and gulp and extensions and NuGet packages I might use to help, I always end up deciding it's much quicker and simpler for me to just continue to add the files manually. My dev environment makes it a viable solution and the cost of entry and cognitive load to maintain it are very low.Erbil
P
60

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"]);
Puentes answered 21/6, 2016 at 7:43 Comment(13)
I'm a little confused as to how this is the answer to the question. This is almost exactly what Microsoft have for configuring Gulp here (learn.microsoft.com/en-us/aspnet/core/client-side/using-gulp). However as far as I can tell this doesn't take content from my node_modules directory and add it to 'lib' or make it usable in any of my files... I'm very new to this so incredibly confused by the seemingly incredibly complicated new world of Web Development...Spotlight
Complicated alright. I'm ready to abandon front-end altogether and just work on APIs.Doublefaced
This is the right approach in general, but the answer leaves out a crucial step: copying the files from the node_modules folder into the wwwroot folder as a Gulp task. Start with var nodeRoot = './node_modules/'; and add a task that copies the desired subfolder from nodeRoot into the appropriate subfolder of webroot. No time now to elaborate, but if there is interest, I can add details later.Thordis
Why has no one raised the obvious: "Why do we have to ask this question!" Why do we intentionally install files in a location where they cannot be used? Then, because our files are not accessible, we install and configure an elaborate utility to copy them to a location where they can be used. Its really ridiculous.Ottoman
@Sam Because, in general, they are development dependencies, not production dependencies. I agree, it's a burden to have to go through the dance just to get an app setup, but I think Mads Kristensen may have some things on the horizon to help simplify the simple casesPuentes
@Thordis -- there is interest in what that task looks like. Specifically, if we have multiple node_modules; must we write each of the tasks explicitly/separately? I suppose we could use an array, and forEach, but is there a better way? ("task that copies the desired subfolder from nodeRoot into the appropriate subfolder")Wessels
This is not an answer to the question at all. The only what is right here that Gulp can be used for the node modules publishing task.Political
Because the tooling here is crap, basically. Using npm is just using npm, just as you would for anything. There's nothing specific to ASP.NET Core. Everything goes into node_modules because that's what npm does. The gulp task is necessary to move things into the right place, i.e. where you actually need them. I think the problem is that Microsoft provided such a beautiful integration with Bower, but now Bower is dead (or at least dying) and Microsoft hasn't provided any alternative tooling.News
It's only in preview at the moment, but Microsoft are moving from Bower to a lightweight alternative called LibraryManager. It won't work for all use cases (i.e. SPA apps), but for the simple "drop jQuery in a folder" it should be a good option. blogs.msdn.microsoft.com/webdev/2018/04/17/…Puentes
It's my understanding that NPM packages in node_modules also consists of the 'source code' for the for the package as well as its dependencies yes? Unless we as developers have a requirement to also want to debug and step-through the javascript code of a package, all we're really interested in are the files in the 'dist' folder right? So a tool to just deal with copying files from dist to wherever we wish to statically serve files in our project is what's required. Serving node_modules seems wrong. I'm new to webdev so my understanding may well be wrong and I'm happy to be schooled on this.Lowery
@Thordis Hey Doug - you mentioned there being some additional code, would you mind taking a peak at this, seeing if you can help? #51051316Alethiaaletta
project.json is no longer a thing in ASP.NET Core projects, but what is the XML equivalent of these build tasks? Can this answer be modified to include this sample?Wendywendye
@Sock, Nay I say. Libman is terrible and a waste of time! The cdnjs provider is has inadequate selection of even the most commonly used libraries. There's a bootstrap and a twitter-bootstrap. The later is version 4 while the former is version 3. Libman's autosuggest feature doesn't list both of these libraries by typing 'bootstrap'! It took me almost an hour to find version 4 and it was useless since it didn't include the sass files which is part of the official distribution.Biotin
D
48

enter image description here

  • 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)

Dispersant answered 21/6, 2016 at 6:21 Comment(4)
Nice answer, kudos for your work on providing the community with a starter kit!Hand
I successfully built a huge public Angular app for a major UK brand earlier this year, and yet I couldn't even understand most of this answer. I can't even begin to learn it as its all over the place. Literally having a career crisis.Doublefaced
this is a good summary of Do's and Dont's while writing and managing client side scripts and files. Saved my time and research. Kudos to you!Procreant
Unfortunately, Visual Studio (stupidly IMHO) treats the "wwwroot" directory specially, based on its name alone, giving it a special "web root" icon in the solution explorer and marking its contents as "None" by default rather than "Content". If the intention is to put statically-served files in there, and you're using Visual Studio, you should probably leave the name as "wwwroot". I agree it's a bad name though.Lesleylesli
B
33

I give you two answers. npm combined with other tools is powerful but requires some work to setup. If you just want to download some libraries, you might want to use Library Manager instead (released in Visual Studio 15.8).

NPM (Advanced)

First add package.json in the root of you project. Add the following content:

{
  "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"
  }
}

This will make NPM download Bootstrap, JQuery and other libraries that is used in a new asp.net core project to a folder named node_modules. Next step is to copy the files to an appropriate place. To do this we will use gulp, which also was downloaded by NPM. Then add a new file in the root of you project named gulpfile.js. Add the following content:

/// <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"));
});

This file contains a JavaScript code that is executed when the project is build and cleaned. It’s will copy all necessary files to lib2 (not lib – you can easily change this). I have used the same structure as in a new project, but it’s easy to change files to a different location. If you move the files, make sure you also update _Layout.cshtml. Note that all files in the lib2-directory will be removed when the project is cleaned.

If you right click on gulpfile.js, you can select Task Runner Explorer. From here you can run gulp manually to copy or clean files.

Gulp could also be useful for other tasks like minify JavaScript and CSS-files:

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

Library Manager (Simple)

Right click on you project and select Manage client side-libraries. The file libman.json is now open. In this file you specify which library and files to use and where they should be stored locally. Really simple! The following file copies the default libraries that is used when creating a new ASP.NET Core 2.1 project:

{
  "version": "1.0",
  "defaultProvider": "cdnjs",
  "libraries": [
    {
      "library": "[email protected]",
      "files": [ "jquery.js", "jquery.min.map", "jquery.min.js" ],
      "destination": "wwwroot/lib/jquery/dist/"
    },
    {
      "library": "[email protected]",
      "files": [ "additional-methods.js", "additional-methods.min.js", "jquery.validate.js", "jquery.validate.min.js" ],
      "destination": "wwwroot/lib/jquery-validation/dist/"
    },
    {
      "library": "[email protected]",
      "files": [ "jquery.validate.unobtrusive.js", "jquery.validate.unobtrusive.min.js" ],
      "destination": "wwwroot/lib/jquery-validation-unobtrusive/"
    },
    {
      "library": "[email protected]",
      "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": "[email protected]",
      "files": [ "list.js", "list.min.js" ],
      "destination": "wwwroot/lib/listjs"
    }
  ]
}

If you move the files, make sure you also update _Layout.cshtml.

Brigettebrigg answered 27/7, 2018 at 11:40 Comment(2)
Library Manager -- never heard of it, but is exactly what I need! This should be the correct answer.Alon
To avoid a gulp error I had to change the first line of the default task in file gulpfile.js to gulp.task('default', function (done) { and then add as a last line in that function the following: done(); Otherwise I would get the error message The following tasks did not complete: Did you forget to signal async completion?Totalitarian
S
28

Install the Bundler and Minifier into Visual Studio Extensions

Then you create a bundleconfig.json and enter the following like :

// 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
  }
]

So the bundler and minifier (gulp based) has access to the source files (which should be excluded from Visual Studio and also excluded from GIT) and puts them into the wwwroot as specified

only side effect every time you save it will run this (but you can set it to run it manually)

Swum answered 7/11, 2017 at 21:46 Comment(6)
After seeing Bower is dead and I can no longer update Bootstrap without switching to NPM, this appears to be my favorite approach. Gulp or Webpack seem overkill compared to this simple solution which is already in the latest MVC project templates. Thank you for sharing!Hydrophobia
How images referenced in css be handled here ? I'm facing a problem with images still in node_modules folder where as css and js were moved to www. Any idea how to fix this ?Dried
Is this IDE-agnostic? How will this work if some of your team is using VS Code, and how does this play into a CD build pipeline?Burkholder
When you install the Bundler and Minifier NuGet package, the docs say it injects build targets which run at build and clean time. I suppose once that's in place, it will work fine regardless of which IDE is used, right? See more: learn.microsoft.com/en-gb/aspnet/core/client-side/…Wendywendye
The bundler is only useful for specifying these scripts outside of the Development environment. From my _Layout page I still have to manually reference the JS and CSS files I need, but the node_modules folder is outside of the website... so I don't think this addresses the problem properly, you still need a Gulp script to copy over the necessary files to my wwwroot folder.Wendywendye
@VPP, I struggled with the same question: CSS files can reference images in other folders via the "url" syntax. You can use Bundler & Minifier to pull the CSS files from node_modules and put them into wwwroot/bundles, but the url references break. In order to keep the url references intact, you need to place the minified CSS file under wwwroot/bundles/some-project-name/css/ and manually copy the image (or font or whatever) files to the correct folder relative to the css folder (e.g. wwwroot/bundles/some-project-name/fonts/). This means you need to look for url references in EVERY CSS file.Guzman
P
7

Instead of trying to serve the node modules folder, you can also use Gulp to copy what you need to wwwroot.

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

This might help too

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

Pteridophyte answered 21/6, 2016 at 4:28 Comment(3)
I really like the second link, seems familiar somehow. ;)Hand
It's not very convenient when you mix ASP.NET Core web app source files with npm modules and client-side code build output. That's the reason why ASP.NET team is removing Gulp, package.json from default ASP.NET MVC project templates.Dispersant
I did not know that. When I was at VS Live in March, they were all about it, but it has changed a lot since then.Pteridophyte
H
7

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.

Hand answered 22/6, 2016 at 11:55 Comment(2)
"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." the fact that from Jan - June and you have to mention is still being relevant is exactly my problem with bothering to learn any of this fly-by-night stuff. I've too much to learn already without wasting my time on fashions. Not your fault David, you're being very helpful, but I don't like this ephemeral new world.Doublefaced
Oh man, this helped so much. Relating npm/node_modules to NuGet/bin was exactly what I needed.Theiss
G
5

Much simpler approach is to use OdeToCode.UseNodeModules Nuget package. I just tested it with .Net Core 3.0. All you need to do is add the package to the solution and reference it in the Configure method of the Startup class:

app.UseNodeModules();

I learned about it from the excellent Building a Web App with ASP.NET Core, MVC, Entity Framework Core, Bootstrap, and Angular Pluralsight course by Shawn Wildermuth.

Gastropod answered 16/10, 2019 at 3:3 Comment(6)
And how do you add npm packages?Pedaias
There are several ways to add npm packages to your project. I prefer to just type them in the package.json file under dependencies node as explained here: https://mcmap.net/q/152535/-how-to-use-npm-and-install-packages-inside-visual-studio-2017Gastropod
@MariuszBialobrzeski Thanks for sharing. This is a neat solution.Dromous
@MariuszBialobrzeski Did you have to do anything additional to deploy the static content from node_modules in your DevOps pipelines? Or did you check in the node_modules folder?Dromous
@Dromous Unfortunately I never had a chance to work with DevOps pipelines. node_modules folder tends to get pretty big with so I would definitely avoid checking it in if possible.Gastropod
All that library does is share the node_modules folder as publicly accessable files, just like one of the answers above do, and as the comment on that answer says: I would highly discourage anyone from statically serving the node_modules folder. a) that's not how the eco-system is designed b) it's a security risk, one of your installed packages might leak sensitive information. The proper way is to set-up a building pipeline (grunt/gulp/node/webpack) that publishes files to a src or whatever folder dedicated to serving static front-end files – CervEdCalyptra
B
2

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

The article links to the gulpfile on GitHub where he's implemented the strategy in the article. You could just copy and paste most of the gulpfile contents into yours, but be sure to add the appropriate packages in package.json under devDependencies: gulp gulp-uglify gulp-concat rimraf merge-stream

Brookebrooker answered 5/1, 2018 at 21:39 Comment(0)
P
1

I've found a better way how to manage JS packages in my project with NPM Gulp/Grunt task runners. I don't like the idea to have a NPM with another layer of javascript library to handle the "automation", and my number one requirement is to simple run the npm update without any other worries about to if I need to run gulp stuff, if it successfully copied everything and vice versa.

The NPM way:

  • The JS minifier is already bundled in the ASP.net core, look for bundleconfig.json so this is not an issue for me (not compiling something custom)
  • The good thing about NPM is that is have a good file structure so I can always find the pre-compiled/minified versions of the dependencies under the node_modules/module/dist
  • I'm using an NPM node_modules/.hooks/{eventname} script which is handling the copy/update/delete of the Project/wwwroot/lib/module/dist/.js files, you can find the documentation here https://docs.npmjs.com/misc/scripts (I'll update the script that I'm using to git once it'll be more polished) I don't need additional task runners (.js tools which I don't like) what keeps my project clean and simple.

The python way:

https://pypi.python.org/pyp... but in this case you need to maintain the sources manually

Pater answered 16/3, 2018 at 17:34 Comment(0)
H
1

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.

Hydrastis answered 19/5, 2019 at 0:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.