javascript is your (auto)mate
TRANSCRIPT
JS is your mateGianluca EspositoCuriosity Driven DeveloperFront-end Developer
Browsers
It began...
Framework
Mobile
Server
Database
Headless
Isomorphic
Desktop
Language
OS
Hardware
noduino
is a platform
JS is your (auto)mateesposi.to/[email protected]
(auto)mate
If you aren't using productivity tools or task automation, you are working too hard.
Grunt… Gulp!
Grunt or Gulp
● Based on files
● Configuration over code
● 4300+ plugins
● Task runner
● Based on streams
● Code over configuration
● Build system
● 1200+ plugins
Grunt or Gulp
grunt-gulp gulp-grunt
npm
Grunt project
package.jsonused by npm to store metadata for projects published as npm modules
Gruntfile.js or Gruntfile.coffee used to configure or define tasks and load Grunt plugins
package.json
$ npm init
{
"name": "(auto)mate",
"version": "0.0.1",
"description": "JS is your (auto)mate",
"author": "Gianluca Esposito <[email protected]>",
"license": "ISC"
}
Grunt
$ npm install -g grunt-cli
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
// Task configuration.
jshint: {
options: {
[...]
},
gruntfile: {
src: 'Gruntfile.js'
},
lib_test: {
src: ['lib/**/*.js', 'test/**/*.js']
}
},
nodeunit: {
files: ['test/**/*_test.js']
},
watch: {
gruntfile: {
files: '<%= jshint.gruntfile.src %>',
tasks: ['jshint:gruntfile']
},
lib_test: {
files: '<%= jshint.lib_test.src %>',
tasks: ['jshint:lib_test', 'nodeunit']
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-nodeunit');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task.
grunt.registerTask('default', ['jshint', 'nodeunit']);
};
Gruntfile.js
module.exports = function(grunt) {
// Do grunt-related things in here
};
The "wrapper" function
// Project configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
[...]
});
Project configuration
// Task configuration
jshint: {
gruntfile: {
src: 'Gruntfile.js'
}
},
watch: {
gruntfile: {
files: '<%= jshint.gruntfile.src %>',
tasks: ['jshint:gruntfile']
}
}
Task configuration
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
// Defines the default task.
grunt.registerTask('default', ['jshint']);
Loading Grunt plugins and tasks
package.json
{
"name": "(auto)mate",
[...]
"devDependencies": {
"grunt": "^0.4.5"
}
}
$ npm install grunt --save-dev
package.json
[...]
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-jshint": "^0.11.0",
"grunt-contrib-watch": "^0.6.1"
}
$ npm install grunt-contrib-jshint
grunt-contrib-watch --save-dev
grunt
// On already configured projects:
$ npm install
$ grunt
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
// Task configuration.
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
unused: true,
boss: true,
eqnull: true,
browser: true,
globals: {
jQuery: true
}
},
gruntfile: {
src: 'Gruntfile.js'
}
},
watch: {
gruntfile: {
files: '<%= jshint.gruntfile.src %>',
tasks: ['jshint:gruntfile']
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task.
grunt.registerTask('default', ['jshint']);
};
Houston... jshint: { options: { curly: true, eqeqeq: true, immed: true, latedef: true, newcap: true, noarg: true, sub: true, undef: true, unused: true, boss: true, eqnull: true, browser: true, globals: { jQuery: true } }, gruntfile: { src: 'Gruntfile.js' } }, watch: { gruntfile: { files: '<%= jshint.gruntfile.src %>', tasks: ['jshint:gruntfile'] } }
{
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Task configuration.
jshint: require('./grunt/config/jshint'),
watch: require('./grunt/config/watch')
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task.
grunt.registerTask('default', ['jshint']);
};
Modulemodule.exports = {
options: {
node: true,
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
unused: true,
boss: true,
eqnull: true,
browser: true,
globals: {
jQuery: true
}
},
gruntfile: {
src: 'Gruntfile.js'
}
};
{
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Task configuration.
jshint: require('./grunt/config/jshint'),
watch: require('./grunt/config/watch')
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task.
grunt.registerTask('default', ['jshint']);
};
Rinse, Repeat
package.json
{
[...]
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-jshint": "^0.11.0",
"grunt-contrib-watch": "^0.6.1",
"load-grunt-config": "^0.16.0"
}
}
$ npm install -D load-grunt-config
Gruntfile.js
module.exports = function(grunt) {
var path = require('path');
require('load-grunt-config')(grunt, {
// path to task.js files, defaults to grunt dir
configPath: path.join(process.cwd(), 'grunt/config')
});
};
WebDev Workflow
WebDev workflow
$ npm install -D grunt-preprocess
grunt-contrib-clean
grunt-contrib-copy
grunt-contrib-concat
grunt-contrib-uglify
grunt-contrib-cssmin
grunt-contrib-imagemin
aliases.js[...]
'default': 'connect',
'build': [
'clean:build',
'copy',
'concat',
'clean:js',
'uglify',
'cssmin',
'clean:css',
'imagemin'
]
require('load-grunt-config')(grunt, {
// path to task.js files, defaults to grunt dir
configPath: path.join(cwd, 'grunt/config'),
//data passed into config. Can use with <%= var %>
data: {
src: 'src/',
dest: 'grunt/build/',
minjs: 'js/build.min.js',
mincss: 'css/build.min.css'
},
// Optionally you can use jit-grunt instead of load-grunt-tasks
jitGrunt: {
jitGrunt: true
}
Gruntfile.js
clean.js
module.exports = {
build: ['<%= dest %>*'],
js: [
'<%= dest %>js/*', '!<%= dest %>'+'<%= minjs %>'
],
css: [
'<%= dest %>css/*', '!<%= dest %>'+'<%= mincss %>'
]
};
$ grunt clean
copy.jsmodule.exports = {
main: {
expand: true,
cwd: '<%= src %>',
src: ['**'],
dest: '<%= dest %>'
},
[...copy dependencies...]
}
$ grunt copy
concat.js
module.exports = {
build: {
src: [
'<%= dest %>js/*.js'
],
dest: '<%= dest %>' + '<%= minjs %>'
}
};
$ grunt concat
uglify.jsmodule.exports = {
options: {
compress: {
drop_console: true
}
},
build: {
files: [{
expand: true,
src: '<%= dest %>' + '<%= minjs %>'
}]
}
};
$ grunt uglify
clean.jsvar dest = '<%= dest %>';
module.exports = {
build: [dest + '*'],
js: [
dest + 'js/*', '!' + dest + '<%= minjs %>'
],
css: [
dest + 'css/*', '!' + dest +'<%= mincss %>'
]
};
$ grunt clean:js
cssmin.js
module.exports = {
build: {
files: {
'<%= dest %><%= mincss %>': ['<%= dest %>' + 'css/*.css']
}
}
};
$ grunt cssmin
imagemin.jsmodule.exports = {
dynamic: {
files: [{
expand: true,
cwd: '<%= src %>',
src: ['img/**/*.{png,jpg,gif}'],
dest: '<%= dest %>'
}]
}
};
$ grunt imagemin
Bonus CLI
# Disable writing files (dry run)
$ grunt taskname --no-write
# Verbose mode. A lot more information
output
$ grunt taskname --verbose
jQuery/Gruntfile.jsjQuery-UI/Gruntfile.js
Angular.js/Gruntfile.jsReact/Gruntfile.js
Atom/Gruntfile.coffeeBrackets/Gruntfile.js
Gruntfiles
PopCornTime/Gruntfile.js
typeahead.js/Gruntfile.jsBootstrap/Gruntfile.js
Wordpress/Gruntfile.jsGhost/Gruntfile.js
Grunt/Gruntfile.js
Day-to-day workflow
$ npm install -D
grunt-http
grunt-wget
grunt-responsive-images
grunt-contrib-compress
http.jsvar path = require('path');
var cwd = process.cwd();
module.exports = function(grunt, options) {
var dest = path.join(cwd, '<%= src %>' + '/api.json');
return {
api: {
options: {
url: 'http://www.splashbase.co/api/v1/images/latest'
},
dest: dest
}
};
};
$ grunt http
wget.js
$ grunt wget
module.exports = function(grunt, options) {
var dest = '<%= src %>';
var json = grunt.file.readJSON(path.join(cwd, dest + '/api.json'));
var src = [];
json.images.forEach(function(image) {
src.push(image.url);
});
return {
baseUrl: {
options: {
overwrite: true
},
src: src,
dest: dest
}
};
};
responsive_images.js
$ grunt responsive_images
module.exports = {
resize: {
options: {
sizes: [{width: 1024}]
},
files: [{
expand: true,
src: ['<%= src %>/**.{jpg,gif,png}'],
custom_dest: '<%= dest %>/{%= width %}/'
}]
}
};
compress.js
$ grunt compress
module.exports = {
main: {
options: {
archive: '<%= dest %>/dest.zip'
},
files: [{
flatten: true,
src: ['<%= dest %>/**/**.{jpg,gif,png}'],
filter: 'isFile'
}]
}
};
(auto)mate
grunt-nodemailer grunt-dropbox
Phase 3: Profit
Files
grunt-shellgrunt-exec
grunt-run-java
grunt-replacegrunt-include-replacegrunt-strip-code
CLI
grunt-curlgrunt-httpgrunt-wgetgrunt-http-upload
HTTP
Deploy
grunt-gitgrunt-push-svn
Versioning
grunt-jscs
grunt-phplint
grunt-karmagrunt-mocha-test
Style Guide
grunt-jenkinsgrunt-sshgrunt-ftpushgrunt-ec2grunt-aws-s3grunt-cloudfrontgrunt-rackspace