As you most likely already know, Gulp is a powerful task runner toolkit that we will use to automate some time-consuming tasks in our development workflow. If you never worked with a task runner, think of it as a batch file or, even better, a PowerShell script powered with some useful web development tools such as file concatenation, js/css shrinking, and more.
You will notice that, together with Gulp, we're also installing some Gulp-related plugins:
gulp-clean: This deletes the contents of the destination folders gulp-concat: This merges multiple files into one
gulp-sourcemaps: This generates the Source Maps gulp-typescript: This compiles TypeScript files into JS gulp-uglify: This minifies JavaScript files
Configuring Gulp is as simple as adding the Gulp Configuration file to your project. You can do that just like you did with the NPM Configuration file, right-click on the root project node in the Solution Explorer and select Add, then New Item. From the client-side tree panel, locate and select the Gulp Configuration file and add a gulpfile.js file to the project root.
The Gulp configuration file, generally known as Gulpfile, is basically a list of tasks and commands that Gulp will execute, written using a mostly readable JavaScript syntax.
Working with it can be tricky at first, especially if you want to use it to handle complex tasks. Digging too much into it would take us out of the scope of this book, so we'll just see how we can tell it to do a rather simple set of jobs, merge all the JavaScript files in the /Scripts/ folder, minus those in a directory for third-party scripts/libraries, into a single, minified all.min.js file which will be generated into the wwwroot folder. This can be obtained with the following code:
var gulp = require('gulp'),
gp_clean = require('gulp-clean'), gp_concat = require('gulp-concat'),
gp_sourcemaps = require('gulp-sourcemaps'), gp_typescript = require('gulp-typescript'), gp_uglify = require('gulp-uglify');
/// Define paths var srcPaths = {
app: ['Scripts/app/main.ts', 'Scripts/app/**/*.ts'], js: ['Scripts/js/**/*.js']
// Compile, minify and create sourcemaps all TypeScript files and place them to wwwroot/app, together with their js.map files.
gulp.task('app', function () { return gulp.src(srcPaths.app) .pipe(gp_sourcemaps.init())
.pipe(gp_typescript(require('./tsconfig.json').compilerOptions)) .pipe(gp_uglify({ mangle: false }))
return gulp.src(destPaths.app + "*", { read: false }) .pipe(gp_clean({ force: true }));
});
// Copy all JS files from external libraries to wwwroot/js gulp.task('js', function () {
return gulp.src(srcPaths.js)
// .pipe(gp_uglify({ mangle: false })) // disable uglify
// .pipe(gp_concat('all-js.min.js')) // disable concat .pipe(gulp.dest(destPaths.js));
});
// Delete wwwroot/js contents gulp.task('js_clean', function () {
return gulp.src(destPaths.js + "*", { read: false }) .pipe(gp_clean({ force: true }));
});
// Watch specified files and define what to do upon file changes gulp.task('watch', function () {
gulp.watch([srcPaths.app, srcPaths.js], ['app', 'js']);
});
// Global cleanup task
gulp.task('cleanup', ['app_clean', 'js_clean']);
// Define the default task so it will launch all other tasks gulp.task('default', ['app', 'js', 'watch']);
Here's a brief explanation of what these commands actually do:
In lines 1-6, we set up Gulp and the required plugins. Notice that every one of them will be initialized into a variable, as that's the way Gulp works.
In lines 8-17,we define the file paths we will use. Doing that here will allow us to write them only once, thus making the Gulp file easier to maintain. Notice that we're splitting the source and the destination paths into two distinct objects, this will mentally help us to keep the development environment separated from the production one.
In lines 19-27, we have the app task, which is the most important and complex one. This task makes use of three different plugins: sourcemaps, typescript, and uglify. Notice how each line is bound to a specific plugin action, which takes care of a single job, following the “It should do one thing” paradigm Gulp is all about.
Line 21 defines the source files, line 22 initializes the sourcemaps plugin, line 23 instructs the plugin to fetch the TypeScript compiler options from the
tsconfig.json file, and so on.
In lines 29-33, we have the app_clean task, which will erase every file and subfolder within the wwwroot/app target path.
In lines 35-39, we define the js task, which is meant to publish external
JavaScript libraries manually added to the project. This is a rather simple task, as it performs a mere copy of the .js files from a source folder into its production counterpart. Notice how we could easily choose to also minify and/or concatenate the source files into a single one by uncommenting a few lines of code. However, since this task is meant to handle third-party JavaScript libraries, it would be wise not to manipulate their code.
In lines 43-47, there's the js_clean task that will erase everything within the wwwroot/js target path.
In lines 49-52, we have the watch task. This is basically a file watcher/monitoring task that will execute the app and js tasks if one or more of their source files will change.
In lines 54-55, we created a cleanup task that will erase the content of all destination paths by launching the app_clean and js_clean tasks. It can be useful to reset these folders to their initial state.
Last but not least, in lines 57-58, we define the default task that will execute all the other tasks, including watch, within a single call. This is the one we will launch.
It's worth noting that the uglify plugin requires the mangle option to be set to false: this is a workaround for a bug in the Angular 2 RC5 that will hopefully be fixed in future releases. For more info regarding this topic, check out the following URL from the official Angular 2 GitHub
repository: https://github.com/angular/angular/issues/1 618. To execute the Gulp file, right-click on it from the Solution Explorer and choose Task Runner Explorer, or open it manually by selecting it from File, Other Windows in the Visual Studio 2015 main menu bar. Once opened, click the refresh button, then right-click the default task and select Run to activate it.
Once you do that, the watch task we just created will silently run in background, keeping tracks of our changes and act accordingly. Notice the default (running) word within the tab label, which will remind us that there is still an ongoing task: closing that console window will immediately shut it down.
That's everything we'll ever need from Gulp for this project; there's no need for us to go further. If you want to learn more about Gulp and its configuration file syntax, you will find a lot of resources and documentation, together with a lot of useful samples, in the official website at the following address: http://gulpjs.com/.