Do you currently use Grunt?
Do you test your JavaScript?
Do you combine and minify your JavaScript?
Do you lint your JavaScript?
Do you do use pre-compiled languages like LESS or CoffeeScript (you hipster!)?
npm install -g grunt-cli
Local Grunt should be installed in each projects root folder.
npm install grunt
This is actually a Node.js file, however it is very useful inside of your Grunt configuration file. It includes:
{ "name": "project-name", <-- no spaces "version" : "0.2.1" "description": "project description", "devDependencies": { "grunt'": "grunt": "~0.4.1", } }
Plugins are what Grunt uses to do "stuff"
"contrib" plugins are the "official" plugins.
Plugins are installed with the npm install
command
npm install grunt-contrib-uglify --save-dev
--save-dev
modifies your package.json file
I HIGHLY recommend the grunt-contrib-watch
plugin.
Gruntfile.js
module.exports = function( grunt ){ grunt.initConfig({ uglify : { all : { files : { 's-code.min.js' : [ 's-code.js', 's-code-page.js'] } } }, jasmine : { min : { src : [ 's-code.min.js'], options : { specs : [ '**test/spec/*.js' ] } } }, }); grunt.loadNpmTasks( 'grunt-contrib-uglify'); grunt.loadNpmTasks( 'grunt-contrib-jasmine'); };
module.exports = function( grunt ){ //load grunt grunt.initConfig({ }); //configure tasks grunt.loadNpmTasks( 'grunt-contrib-jasmine' ); //load tasks });
grunt.initConfig({ uglify : { ... }, jasmine : { ... }, jslint : { ... } });
The uglify
task below has two targets: dev
and prod
When running grunt you can run any or all of these targets.
grunt.initConfig({ uglify : { dev : { ... }, prod : { ... } } });
Most tasks use input and output files so it is baked right into Grunt.
There are many different ways to pass files into tasks! Choosing the right one will greatly reduce your stress.
This knowledge is assumed, it is excluded from most plugins documentation!
Uses src
and dest
properties.
concat: { prod: { src: ['src/bb.js', 'src/bbb.js'], dest: 'dest/b.js', } }
Uses an object named files
.
The property name is the output file name. The property value is the input files.
uglify: { prod: { files: { 'dest/a.js': ['src/aa.js', 'src/aaa.js'], 'dest/a1.js': 'src/aa1.js', }, } }
Supports multiple src-dest file mappings per-target.
concat: { prod: { files: [ {src: ['src/aa.js', 'src/aaa.js'], dest: 'dest/a.js'}, {src: ['src/aa1.js', 'src/aaa1.js'], dest: 'dest/a1.js'}, ] } }
src
and dest
properites also support additional options.
filter
takes either a function that returns a boolean, or a fs.Stats method name.
files : [ { src : {...}, dest : {...}, filter : function( src ){ return !(/node_modules/.test( src )); } } ]
files : [ { src : {...}, dest : {...}, filter : 'isFile' } ]
grunt.initConfig( { pkg : grunt.file.readJSON( 'package.json' ), uglify : { all : { files : { 's-code.min.<%= pkg.version %>.js' : sourceFiles } } } })
grunt
command.bittersweetryan$ grunt
grunt.initConfig({ uglify : { dev : { ... }, prod : { ... } }, concat: { dev : { ... } } });
grunt
command.target
for that task.bittersweetryan$ grunt uglify
grunt.initConfig({ uglify : { dev : { ... }, prod : { ... } }, concat: { dev : { ... } } });
To run only a single target, append the target name to the task with a :
bittersweetryan$ grunt uglify:dev
grunt.initConfig({ uglify : { dev : { ... }, prod : { ... } }, concat: { dev : { ... } } });
registerTask()
function.registerTask
is usually don at the end of your module.exports function.Override running all tasks when grunt
is run with no targets.
grunt.registerTask( 'default',['jasmine','concat','uglify'] );
Only run grunt
:prod
targets:
grunt.registerTask( 'prod',['jasmine:prod','concat:prod','uglify:prod'] );
bittersweetryan$ grunt prod
Lets say we wanted to be able to dynamically pass an environment target into the last example. We can do that with command line arguments.
grunt --varname=value
var env = grunt.option( 'env' ); var tasks = [ 'jasmine', 'concat', 'uglify' ]; grunt.registerTask('default', tasks.map( function( task ){ return task + ':' + env; } ) );
grunt --env=prod