Using NPM and Gulp in Visual Studio 2017

By default new Web Applications created in Visual Studio 2017 use Bower for managing external libraries such as jQuery and Bootstrap, however Bower is no longer best practice (and seemed a bit flaky in Visual Studio anyway) and so for new projects I now use npm for managing packages.

Using npm in Visual Studio takes a bit more work than Bower to setup but is better supported and gives more control over the library files that are published.


First off, install Node.js which will install npm for you.

As per this article it’s easier to use npm from the command line and installing the extension “Open Command Line” means you can open a command prompt scoped to any folder in your solution from a right click.


Open a command prompt scoped to your project folder and run npm init to initialise npm in your project, this will ask you for some basic details about your project but you can just accept the defaults and edit the values later in the configuration if you’d like.

Once npm has been initialised you can either add a configuration file manually and start adding packages from there or install a package from the command line and have it create the configuration file for you which is what I usually do, to install jQuery use npm install jquery --save.

The package.json file will now be added to your project and the folder node_modules will be created and jQuery downloaded into it. By default node_modules will be hidden so to view it you’ll need to enable the “Show All Files” option in the solution explorer.

Your package.json file will look something like that below with descriptive values set from the initialisation command and dependencies on any packages that you’ve installed.

  "name": "FileUpload",
  "version": "0.0.0",
  "description": "",
  "main": "gulpfile.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  "author": "",
  "license": "ISC",
  "dependencies": {
    "azure-storage": "^2.8.1",
    "bootstrap": "^4.0.0",
    "gulp": "^3.9.1",
    "gulp-concat": "^2.6.1",
    "gulp-uglify": "^3.0.0",
    "jquery": "^3.3.1",
    "jquery-validation": "^1.17.0",
    "jquery-validation-unobtrusive": "^3.2.8",
    "merge-stream": "^1.0.1",
    "popper.js": "^1.14.0",
    "rimraf": "^2.6.2"

Installing the desired packages into the node_modules folder is fine, but as this is outside of the projects wwwroot folder there needs to be some way to access it from the running web application, this is where gulp comes in.

There is also a quick and temporary solution for making the node_module folder visible as detailed here which uses the AddStaticFiles middleware to add node_modules in the same way that wwwroot is added.

This is done by adding a second AddStaticFiles middleware in the Configure method of Startup.cs like so.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
	if (env.IsDevelopment())

	// For wwwroot directory

	// Add support for node_modules but only during development **temporary**
	if (env.IsDevelopment())
		app.UseStaticFiles(new StaticFileOptions()
			FileProvider = new PhysicalFileProvider(
			  Path.Combine(Directory.GetCurrentDirectory(), @"node_modules")),
			RequestPath = new PathString("/vendor")

	app.UseMvc(routes =>
			name: "default",
			template: "{controller=Home}/{action=Index}/{id?}");

These can then be referenced in your project from the vendor directory as you would with those from the wwwroot directory.

<link rel="stylesheet" href="~/vendor/bootstrap/dist/css/bootstrap.css" />
<script src="~/vendor/jquery/dist/jquery.js"></script>

Gulp is a better solution to this problem as rather than just copying the whole node_modue folder when the project is published it can be used to only copy specific files as well as to perform actions such as minification upon them.


I got gulp working by using this guide as well Shawn Wildermuth’s article linked to above.

The first step is to install gulp using npm from a command line scoped to the project folder.

npm install gulp --save

Various plugins can then be installed to add additional features.

The ones installed in the package.json file above are used in this example from Shawn Wildermuth which I’ve used as the basis of my gulpfile.js below.

The file gulpfile.js can be added to your project by right clicking and adding a new item.

This file contains javascript which determines what files are copied and where to as well as the required transformations.

/// <binding BeforeBuild='default' />
This file is the main entry point for defining Gulp tasks and using Gulp plugins.
Click here to learn more.

var gulp = require('gulp');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var rimraf = require("rimraf");
var merge = require('merge-stream');

gulp.task("minify", function () {

    var streams = [

    return merge(streams);

// Dependency Dirs
var deps = {
    "azure-storage": {
        "lib/**/**/**/*": ""
    "bootstrap": {
        "dist/**/*": ""
    "jquery": {
        "dist/*": ""
    "jquery-validation": {
        "dist/**/*": ""
    "jquery-validation-unobtrusive": {
        "dist/*": ""
    "popper.js": {
        "dist/**/*": ""

gulp.task("clean", function (cb) {
    return rimraf("wwwroot/vendor/", cb);

gulp.task("scripts", function () {

    var streams = [];

    for (var prop in deps) {
        console.log("Prepping Scripts for: " + prop);
        for (var itemProp in deps[prop]) {
            streams.push(gulp.src("node_modules/" + prop + "/" + itemProp)
                .pipe(gulp.dest("wwwroot/vendor/" + prop + "/" + deps[prop][itemProp])));

    return merge(streams);


gulp.task("default", ['clean', 'minify', 'scripts']);

To test that the code in gulpfile.js is working as intended you can right click on it and select “Task Runner Explorer”, this will open a window allowing you to run each function manually as well as to bind them to project events so that it will run before each project build for example.


Laurie Dickinson · 27th September 2018 at 2:51 pm

Thanks, this is very helpful and quite clear. One question: What is the index.js referenced in the package.json file. Does that do anything or does gulp just look for the gulpfile.js file?

    Shinigami · 27th September 2018 at 3:37 pm

    Hmm, I think that must have come from the article that I initially got this from when researching this integration. Looking at my current projects the main value is gulpfile.js which is what I’d expect, I’ll update the article accordingly. Good spot!

Kevin Biasci · 12th October 2018 at 12:07 am

Thanks a lot for this, I was in the process of removing all the Bower references from my project and replacing them with LibMan/NPM. You saved my day 🙂

ROGÉRIO MORALEIDA · 16th November 2018 at 8:23 pm

Tanks.. Plase send demo in github.

    Shinigami · 18th November 2018 at 3:05 pm

    Hi, you can see this in action here.

      Alex · 5th December 2018 at 11:13 pm

      Hey Shinigami for some reason i can’t run the demo, i downloaded the solution and opened it but for some reason it doesn’t create _layout or does anything really, doesn’t load the css either, i have tried a lot of things and it comes to this very scenario the css won’t load and the _layout won’t be created either.

      Node.js is running, what can i do?

        Shinigami · 6th December 2018 at 11:34 am

        Hi Alex, when you say you downloaded the solution did you just download the solution file? I’ve just cloned the GitHub project in Visual Studio and that ran fine for me.

        If you clone in the Team Explorer tab of Visual studio then that should bring down all the required files and hopefully work for you.

          Alex · 6th December 2018 at 3:13 pm

          Downloading right now will report results.

Ehsan Sajjad · 21st November 2018 at 1:44 pm

Does this required installing nodejs first on the machine ?

    Shinigami · 21st November 2018 at 2:48 pm

    Yep, this requires node.js in order to use npm. I’ll update the post to make this clearer.

Kenneth Purtell · 3rd December 2018 at 5:47 pm

“bootstrap”: {
“dist/**/*”: “”

Thanks for this. Very informative and helpful.

How would one edit the json to get both bootstrap scss and bootstrap js files?

For example I would like to pull down bootstrap’s scss and js files (not all the js selection, just bootstrap.js from “node_modules/bootstrap/dist/js/bootstrap.js”.


    Kenneth Purtell · 3rd December 2018 at 6:06 pm

    I think I found a solution –

    “bootstrap”: {
    “**/**/*”: “”

    This pulls in everything. I can include the required paths to a sub-set of those assets and include it in the gulp.src array.

      Shinigami · 3rd December 2018 at 10:27 pm

      Yep, that will copy over everything in the bootstrap folder. If you’re just interested in the js and scss folders then the below will get them for you.

      “bootstrap”: {
      “js/**/*”: “js”,
      “scss/**/*”: “scss”

Kamran · 7th June 2019 at 5:08 pm

just word of caution in order to run successfully make sure following are installed i learn hard way 🙂

npm install –save-dev gulp
npm install –save-dev gulp-uglify
npm install –save-dev gulp-concat
npm install –save-dev rimraf
npm install –save-dev merge-stream

Same tiome check Option from tool Option > Project and Sol;utions > Web Package Management > External Web Tools Select “.\node_modules\.bin” change the order move it down mine first one is $(VSInstalledExternalTools)

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *