Isaac Levin
Isaac Levin

Reputation: 2909

Using NPM/Bower over Nuget MVC Site with bundling

I am trying to train myself on the new preferred way of referencing Front-end libraries in .Net Applications, so I have started to read into doing this with Gulp. I have read this article on replacing the Nuget packages with ones from bower

https://blogs.msdn.microsoft.com/cdndevs/2015/02/17/using-bower-with-visual-studio/

And this one to use Gulp

http://www.davepaquette.com/archive/2014/10/08/how-to-use-gulp-in-visual-studio.aspx

However I am having some trouble putting it all together. I want together some process that will not only replace all the Pre-Installed Nuget packages with bower packages, but also minify and bundle them with gulp instead of using the Web.Optimization library. The first link walks through doing that, but the gulp script is not providing the output I would expect (no dist folders for instance). This SO question has some good answers, but I am not seeing how I bundle all the libraries from bower (I read through all the comments and answers).

Using Grunt, Bower, Gulp, NPM with Visual Studio 2015 for a ASP.NET 4.5 Project

Obviously this stuff is new to me so I will get confused, but I want to make sure I do it the right way.

I am using Visual Studio 2015 and am creating a new MVC 4.5.2 Application, and I want to have all front-end libraries referenced and bundled/minified without using any .Net libraries. It seems at this point far easier to do it the old way

Upvotes: 3

Views: 1226

Answers (1)

Paul Swetz
Paul Swetz

Reputation: 2254

The question is a little broad but Ill hit on the key points since I've been doing this exact thing for a few weeks now.

Break what you are doing into two phases - replacing packages from nuget as phase one and replacing the .net bundling as the other.

Phase one - pretty simple actually, remove (uninstall) all the packages you have from nuget that have bower equivalents, then add those packages via the bower commands (don't forget to --save and --save-dev where needed). Then replace your script locations in the .net bundling with the new locations in bower_components. Once you can confirm your site works under this new layout while still using .net bundling you are ready for phase two.

Now for phase two, first and formost you need to learn the concept of 'globs' which are basically wild card based include and excludes for files in gulp. Probably the single most helpful thing I've found to help with this is the gulp plugin main-bower-files. So to create a good glob to start with I had this...

 var paths = {};
 paths.baseReleaseFolder = "app";
paths.baseJSReleaseFile = "site.min.js";
 paths.jsSource = mainBowerFiles();//this gets all your bower scripts in an array
.concat([        
    "node_modules/angular/angular.js",//my angular is loaded via npm not bower because the bower version was giving me dependency issues (bug)
    "node_modules/angular-route/angular-route.js",
    "Source/output.js",//generated by MY typescript compiler
    "!/Scripts", //this is an exclude
     "!**/*.min.js" //also an exclude
]);

This is basically saying I want to select all the DISTRO bower plugins files needed to run whatever, include my angular js, and exclude anything in my scripts folder (typescript files and outputs) and exclude any ALREADY minified files (I want to do it all myself as one concatenated file).

Now I separate the js and css operations and wrap another event to call both so I end up with

 gulp.task("min", ["min:js", "min:css"]);
 gulp.task("min:js", function () {});
gulp.task("min:css", function () {});

Now as an example of how that works I have the following in my min:js

gulp.task("min:js", function () {
var jsFilter = filter('**/*.js', { restore: true });//extra file safty incase my glob is getting non js files somehow
return gulp
    .src(paths.jsSource) //this is the 'glob' IE the file selector 
    .pipe(jsFilter) //enforce my filter from above (gulp-filter)
    //.pipe(debug()) //useful to output what files are in use (gulp-debug)
    .pipe(sourcemaps.init({loadMaps:true})) //create sourcemaps for final output(gulp-sourcemaps)
    .pipe(uglify()) //min and ugilfy files on the way to next step (gulp-uglify)
    .pipe(concat(paths.baseReleaseFolder + "/" + paths.baseJSReleaseFile)) //this takes all the files in the glob and creates a single file out of them in app/site.min.js
    .pipe(rev()) //ignore this, cache-busting but requires work on the .net side to load the files, basically adds the file hash to the file name in the output
    .pipe(sourcemaps.write(".")) //actually write my .map.js file to the final destination
    .pipe(gulp.dest(".")) //write the final site.min.js to its location
    .pipe(jsFilter.restore); //not sure but all filter examples do this.
});

So when this is all said and done I end up with a single site.min.js file in the 'app' folder that is the concatenated, minified, uglified version off all my bower components (and whatever else the glob hit). Now just to give you an idea on how plugin intensive using gulp is this is the declaration of all plugins I load into my main gulp script to do bascailly what .net bundling does for you....

var gulp = require('gulp'),
rimraf = require("gulp-rimraf"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
debug = require("gulp-debug"),
uglify = require("gulp-uglify"),
filter = require("gulp-filter"),
rename = require("gulp-rename"),
rev = require('gulp-rev'),
sourcemaps = require('gulp-sourcemaps'),
csslint = require('gulp-csslint'),
jslint = require('gulp-jslint'),
typescript = require("gulp-typescript"),
tslint = require("gulp-tslint"),
runSequence = require('run-sequence'),    
mainNodeFiles = require("npm-main-files"),
mainBowerFiles = require('main-bower-files');

You probably don't need all of these (some are typescript, some are linters)

Edit: Heres my css function

gulp.task("min:css", function () {
var cssFilter = filter('**/*.css', { restore: true });
return gulp
    .src(paths.cssSource)
    .pipe(cssFilter)
    //.pipe(debug())
    .pipe(sourcemaps.init({ loadMaps: true }))
    .pipe(concat(paths.baseReleaseFolder + "/" + paths.baseCSReleaseFile))
    .pipe(cssmin())
    .pipe(rev())
    .pipe(sourcemaps.write("."))
    .pipe(gulp.dest("."))        
    .pipe(cssFilter.restore);

});

Upvotes: 4

Related Questions