Created
October 8, 2012 10:24
-
-
Save dpashkevich/3851841 to your computer and use it in GitHub Desktop.
Grunt setup for a big project
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ | |
"name": "SubModule", | |
"src": [ | |
"SubModule/css/Sub.1.css", | |
"SubModule/css/Sub.2.css", | |
"SubModule/css/Sub.3.css" | |
], | |
"dest": "SubModule/css/submodule-all.css" | |
}, { | |
"name": "app", | |
"src": [ | |
"css/style.css" | |
], | |
"dest": "css/awesome-project-all.css" | |
} | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Directory structure | |
SubModule/ | |
css/ | |
... | |
js/ | |
... | |
images/ | |
... | |
ExtJS/ | |
css/ | |
ext-all.css | |
js/ | |
ext-all.js | |
ext-all-dev.js | |
overrides.js | |
images/ | |
... | |
css/ | |
... | |
js/ | |
... | |
images/ | |
... | |
awesome-project.json | |
jsfiles.json | |
cssfiles.json | |
index.tmpl | |
grunt.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*global module:false*/ | |
module.exports = function(grunt) { | |
var | |
// Note: pre-minified static resources (ExtJS) will be added before all project files | |
jsBundle = grunt.file.readJSON('jsfiles.json'), | |
cssBundle = grunt.file.readJSON('cssfiles.json'), | |
// flat array of all source js files | |
jsFiles = [], | |
// flat array of all source css files | |
cssFiles = []; | |
// create flat arrays of all source files | |
(function processBundles() { | |
var i, len; | |
for(i = 0, len = jsBundle.length; i < len; i++) { | |
// append to flat array of all source files | |
jsFiles = jsFiles.concat(jsBundle[i].src); | |
} | |
for(i = 0, len = cssBundle.length; i < len; i++) { | |
// append to flat array of all source files | |
cssFiles = cssFiles.concat(cssBundle[i].src); | |
} | |
})(); | |
// Import npm tasks | |
grunt.loadNpmTasks('grunt-contrib-clean'); | |
grunt.loadNpmTasks('grunt-contrib-mincss'); | |
// Import custom tasks | |
grunt.loadTasks('build/tasks'); | |
// Project configuration. | |
grunt.initConfig({ | |
pkg: '<json:awesome-project.json>', | |
meta: { | |
banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + | |
'<%= grunt.template.today("yyyy-mm-dd") %>\n' + | |
'<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' + | |
'* Copyright (c) <%= grunt.template.today("yyyy") %> ' + | |
'Pickles&Cows Ltd. */' | |
}, | |
// ExtJS development js | |
extJsDevFile: 'ExtJS/js/ext-all-dev.js', | |
// ExtJS production js | |
extJsProdFile: 'ExtJS/js/ext-all.js', | |
// ExtJS development css file | |
extJsDevCss: 'ExtJS/css/ext-all.css', | |
// ExtJS production css file | |
extJsProdCss: 'ExtJS/css/ext-all.css', | |
// Project files definitions | |
jsBundle: jsBundle, | |
cssBundle: cssBundle, | |
jsFiles: jsFiles, | |
cssFiles: cssFiles, | |
lint: { | |
files: ['grunt.js'].concat(jsFiles) | |
}, | |
concat: { | |
// config generated dynamically | |
}, | |
// index.html builder task options | |
index: { | |
src: 'index.tmpl' | |
/** | |
* These properties are set dynamically depending on build configuration: | |
* dest - destination index.html file path | |
* cssFiles - all css files | |
* jsFiles - all js files | |
*/ | |
}, | |
// file copier | |
copy: { | |
/* copy static resources for production build */ | |
dist: { | |
src: ['images/**/*', 'fonts/**/*', 'ExtJS/images/**/*', 'SubModule/images/**/*'], | |
dest: 'dist/' | |
} | |
}, | |
// js minifier (UglifyJs) | |
min: { | |
// config generated dynamically | |
}, | |
// css minifier | |
mincss: { | |
// config generated dynamically | |
}, | |
// clean up temporary files left after build process (or entire build dir) | |
clean: { | |
dist_entire: 'dist' | |
} | |
}); | |
grunt.registerTask('prod', 'Production build', function() { | |
var | |
path = require('path'), | |
jsBundle = grunt.config('jsBundle'), | |
cssBundle = grunt.config('cssBundle'), | |
// TODO don't hardcode | |
outDir = 'dist/', | |
// target files that need to be included in index.html | |
jsTargets = [], | |
cssTargets = [], | |
// task queue... | |
tasks = []; | |
/** | |
* Iterates over package definitions in a bundle, | |
* generating tasks for concatenating and minifying all files defined in each package. | |
* | |
* @param {Object} o Options object | |
* @param {Array} o.bundle The bundle to process | |
* @param {Array} o.tasks Task queue array to push into | |
* @param {String} o.minTask Task to use for minification | |
* @param {String} o.taskPrefix A prefix to add to generated task names | |
* @param {Array} o.targets Array of target files to push into (paths relative to output directory) | |
* @param {String} o.outDir Output directory for targets | |
*/ | |
function processBundle(o) { | |
var bundle = o.bundle, | |
tasks = o.tasks, | |
minTask = o.minTask, | |
taskPrefix = o.taskPrefix, | |
targets = o.targets, | |
outDir = o.outDir, | |
pkg, | |
dest, | |
taskName; | |
for(var i = 0, len = bundle.length; i < len; i++) { | |
pkg = bundle[i]; | |
// add target file path without the destination directory | |
targets.push(pkg.dest); | |
dest = outDir + pkg.dest; | |
// defining concatenation task for the package | |
taskName = taskPrefix + pkg.name; | |
grunt.config('concat.' + taskName, { | |
src: pkg.src, | |
dest: dest | |
}); | |
// add the task we defined to the queue | |
tasks.push('concat:' + taskName); | |
// defining minification task | |
grunt.config(minTask + '.' + taskName, { | |
// now we're using the same path as src and dest... | |
// dunno if that's a good idea but at least we don't have garbage files to deal with | |
src: dest, | |
dest: dest | |
}); | |
tasks.push(minTask + ':' + taskName); | |
} | |
} | |
// processing js bundle... | |
processBundle({ | |
bundle: jsBundle, | |
tasks: tasks, | |
minTask: 'min', | |
taskPrefix: 'js_', | |
targets: jsTargets, | |
outDir: outDir | |
}); | |
// defining final js concatenation task (prepend banner and statics to the first package in js bundle) | |
grunt.config('concat.js_final', { | |
src: [ | |
grunt.config('extJsProdFile'), | |
'\n\n<banner:meta.banner>', | |
outDir + jsBundle[0].dest | |
], | |
dest: outDir + jsBundle[0].dest | |
}); | |
tasks.push('concat:js_final'); | |
// processing css bundle... | |
processBundle({ | |
bundle: cssBundle, | |
tasks: tasks, | |
minTask: 'mincss', | |
taskPrefix: 'css_', | |
targets: cssTargets, | |
outDir: outDir | |
}); | |
// prepend statics | |
cssTargets.unshift(grunt.config('extJsProdCss')); | |
// copy lib css | |
grunt.config('copy.prod', { | |
src: grunt.config('extJsProdCss'), | |
dest: 'dist/' | |
}); | |
// override data for generating index.html | |
grunt.config('index.dest', outDir + 'index.html'); | |
grunt.config('index.jsFiles', jsTargets); | |
grunt.config('index.cssFiles', cssTargets); | |
tasks = [].concat( | |
// Nuke the entire build directory first... | |
'clean:dist_entire', | |
// Tasks for building JS & CSS | |
tasks, | |
// Copy static resources | |
'copy:dist', | |
'copy:prod', | |
// Generate index.html | |
'index' | |
); | |
// finally run tasks in specified order | |
grunt.task.run(tasks); | |
grunt.log.writeln('Production build complete'); | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module.exports = function( grunt ) { | |
grunt.registerTask( "index", "Generate index.html depending on configuration", function() { | |
var conf = grunt.config('index'), | |
jsFiles = conf.jsFiles, | |
cssFiles = conf.cssFiles, | |
tpl = grunt.file.read(conf.src), | |
tplData = {}, | |
cssIncludes, | |
jsIncludes, | |
targetFile; | |
tplData.title = grunt.config('pkg.title'); | |
/*********** COLLECTING CSS ***********/ | |
grunt.log.writeln('Collecting CSS...'); | |
if(cssFiles && cssFiles.length) { | |
cssIncludes = cssFiles.map(function(v) { | |
return '<link rel="stylesheet" type="text/css" href="' + v + '" />\n'; | |
}).join(''); | |
} | |
tplData.css = cssIncludes; | |
/*********** COLLECTING JAVASCRIPT ***********/ | |
grunt.log.writeln('Collecting JavaScript...'); | |
if(jsFiles && jsFiles.length) { | |
jsIncludes = jsFiles.map(function(v) { | |
return '<script type="text/javascript" src="' + v + '"></script>\n'; | |
}).join(''); | |
} | |
tplData.js = jsIncludes; | |
/*********** WRITING TEMPLATE ***********/ | |
grunt.log.writeln('Finally writing the template...'); | |
targetFile = conf.dest; | |
grunt.file.write(targetFile, grunt.template.process(tpl, tplData)); | |
grunt.log.writeln('Generated \'' + targetFile + '\' from \'' + conf.src + '\''); | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | |
<meta name="google" value="notranslate" /> | |
<title><%= title %></title> | |
<link rel="shortcut icon" href="favicon.ico" /> | |
<%= css %> | |
<%= js %> | |
</head> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ | |
"name": "app", | |
"src": [ | |
"ExtJS/js/overrides.js", | |
"SubModule/js/Sub.1.js", | |
"SubModule/js/Sub.2.js", | |
"SubModule/js/Sub.3.js", | |
"js/debug.js", | |
"js/common.js", | |
"js/data.js", | |
"js/app.js" | |
], | |
"dest": "js/awesome-project-all.js" | |
} | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment