In this chapter we will discuss the process of final build configuration and then actually running automated builds of the sample_project
. We will learn:
The process and syntax for loading a task are quite simple and very straightforward. In fact, the basic way to load a task is a simple one-liner using Grunt's loadNpmTasks
method.
The syntax is:
grunt.loadNpmTasks('name-of-task'),
The name-of-task
, as shown in the example, would be the name of the task as defined in sample_project's package.json devDependencies
object. So, for instance, to load grunt-contrib-uglify
we would specify it as the argument in the loadNpmTasks
method like this:
grunt.loadNpmTasks('grunt-contrib-uglify'),
A little about loadNpmTasks. The loadNpmTasks method is a method that loads plugins installed locally with NPM (it will not load tasks installed via other means) and that have been installed relative to the gruntfile. In order to load tasks not installed with NPM, one would use grunt.loadTasks
, an alias for grunt.task.loadTasks
. Additionally, for tasks that have been installed with NPM, one may also use grunt.task.loadNpmTasks
. The alias makes them synonymous. The syntax difference lies in the synonyms:
grunt.loadTasks('name-of-task'),
is the same as:
grunt.task.loadTasks('name-of-task'),
we also have to do:
grunt.loadNpmTasks('name-of-task'),
which is the same as:
grunt.task.loadNpmTasks('name-of-task'),
The following will provide the code for loading each plugin we are using in the sample_project. Note that we installed all of the plugins using NPM, so we will use the loadNpmTasks method for each plugin.
contrib-jshint
plugin:
grunt.loadNpmTasks('grunt-contrib-jshint'),
contrib-uglify
plugin:
grunt.loadNpmTasks('grunt-contrib-uglify'),
contrib-less
plugin:
grunt.loadNpmTasks('grunt-contrib-less'),
contrib-imagemin
plugin:
grunt.loadNpmTasks('grunt-contrib-imagemin'),
contrib-notify
plugin:
grunt.loadNpmTasks('grunt-notify'),
contrib-open
plugin:
grunt.loadNpmTasks('grunt-open'),
contrib-watch
plugin:
grunt.loadNpmTasks('grunt-contrib-watch'),
For this style of loading, all of the loadNpmTasks calls are placed after the configuration section, as follows:
grunt.loadNpmTasks('grunt-contrib-jshint'), grunt.loadNpmTasks('grunt-contrib-uglify'), grunt.loadNpmTasks('grunt-contrib-less'), grunt.loadNpmTasks('grunt-contrib-imagemin'), grunt.loadNpmTasks('grunt-contrib-watch'), grunt.loadNpmTasks('grunt-notify'), grunt.loadNpmTasks('grunt-open'),
While this is the way in which Grunt documents the usage of loadNpmTasks, there is a more elegant way. By looping through the devDependencies
object to get each one of the dependencies defined within, all of the tasks may be loaded without the need to explicitly load each one. This is done simply with the following syntax:
Object.keys(require('./package.json').devDependencies).forEach(function(dep) { grunt.loadNpmTasks(dep); });
Let's break this down. Object
is the object which contains the properties (or, in this case, tasks properties) that we wish to use. We will use the Object's keys method to return only the names of the properties, which will be the tasks listed as dependencies in devDependencies
. Require includes a defined file and require (./package.json).devDependencies
returns the devDependencies
object in package.json, which is then looped over for each property and returned and loaded with grunt.loadNpmTasks
on each iteration of the loop. Using this approach we could add and remove tasks from package.json and config without having to worry about loading. However, in our case using the Angular-Seed project, there are many tasks in devDependencies
that we do not need within our automated build process. For this reason it will be better to explicitly load each task.
At this time our Gruntfile.js should look like the following:
module.exports = function(grunt) { 'use strict'; grunt.initConfig({ // Metadata. pkg: grunt.file.readJSON('package.json'), banner: '/*! *** DO NOT EDIT THIS FILE *** ' + 'It is automatically generated in the build ' + '<%= pkg.name %> - v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> ' + '<%= pkg.repository %> ' + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;*/ ', // Task configuration. jshint: { files: ['scripts/main.js'], gruntfile: { options: { jshintrc: '.jshintrc' }, src: 'Gruntfile.js' } }, uglify: { options: { banner: '<%= banner %>' }, dist: { src: 'scripts/main.js', dest: 'build/scripts/<%= pkg.name %>.<%= pkg.version %>.min.js' }, }, less: { options: { paths: ["styles"] }, dist: { src: 'styles/main.less', dest: 'styles/main.css' } }, imagemin: { dynamic: { files: [{ expand: true, cwd: 'images/', src: ['**/*.{png,jpg,gif}'], dest: 'dist/' }] } }, notify: { jshint: { options: { title: 'Linting Complete', message: 'jshint finished', } }, uglify: { options: { title: 'Minification Complete', message: 'JavaScript is minified' } }, less: { options: { title: 'LESS Compiled', message: 'CSS is generated' } }, imagemin: { options: { title: 'Images Minified', message: 'Images are minified' } }, watch: { options: { title: 'Watch Started', message: 'Watch is running' } } }, open : { dev : { path: 'http://localhost:8000/app/index.HTML', app: 'Google Chrome' } }, watch: { gruntfile: { files: 'Gruntfile.js', tasks: ['jshint','uglify','less','imagemin'], }, scripts: { files:['scripts/*.js','styles/*.less'], tasks: ['default'] } }, }); grunt.loadNpmTasks('grunt-contrib-jshint'), grunt.loadNpmTasks('grunt-contrib-uglify'), grunt.loadNpmTasks('grunt-contrib-less'), grunt.loadNpmTasks('grunt-contrib-imagemin'), grunt.loadNpmTasks('grunt-contrib-watch'), grunt.loadNpmTasks('grunt-notify'), grunt.loadNpmTasks('grunt-open'), };
We have just one more item to add in order to complete our automated build. This is to create our custom and default tasks. While sample_project won't use a custom task, per se, an example of what this is and why we might want to use one or more custom tasks will be discussed in the next section.
52.15.231.106