module.exports = function(grunt) { // Do grunt-related things in here };
Gruntfile.coffee
, writing plugins, ...) npm install -g grunt-cli
βββ AUTHORS βββ Gruntfile.js # jshint βββ LICENSE-MIT βββ README.md βββ bin β βββ grunt # βββ completion # β βββ bash β βββ zsh βββ lib β βββ cli.js # cli β βββ completion.js # β βββ info.js # βββ package.json 3 directories, 11 files
var resolve = require('resolve').sync; try { gruntpath = resolve('grunt', {basedir: basedir}); } catch (ex) { gruntpath = findup('lib/grunt.js'); // No grunt install found! if (!gruntpath) { if (options.version) { process.exit(); } if (options.help) { info.help(); } info.fatal('Unable to find local grunt.', 99); } } /** * gruntpath -> {HOME_DIR}/node_modules/grunt/lib/grunt.js * .cli() grunt */ require(gruntpath).cli();
βββ AUTHORS βββ CHANGELOG βββ CONTRIBUTING.md βββ Gruntfile.js # jshint, test, watch βββ LICENSE-MIT βββ README.md βββ appveyor.yml βββ docs β βββ README.md βββ internal-tasks # β βββ bump.js β βββ subgrunt.js βββ lib β βββ grunt # β β βββ cli.js β β βββ config.js β β βββ event.js β β βββ fail.js β β βββ file.js β β βββ help.js β β βββ option.js β β βββ task.js β β βββ template.js β βββ grunt.js # β βββ util β βββ task.js # βββ package.json βββ test βββ **/*.js # 22 directories, 71 files
Yes, this is a total hack...
They urge you to do more, but easier than shorter, but βsly ". // bad var foo = 'bar' , bizz = 'bazz'; // better var foo = 'bar'; var bizz = 'bazz'; // bad isOk && doGrunt(); // better if (isOk) { doGrunt(); } // bad isOk ? doGrunt() : doMake(); // better if (isOk) { doGrunt(); } else { doMake(); }
"async": "~0.1.22", "coffee-script": "~1.3.3", "colors": "~0.6.2", "dateformat": "1.0.2-1.2.3", "eventemitter2": "~0.4.13", "findup-sync": "~0.1.2", "glob": "~3.1.21", "hooker": "~0.2.3", "iconv-lite": "~0.2.11", "minimatch": "~0.2.12", "nopt": "~1.0.10", "rimraf": "~2.2.8", "lodash": "~0.9.2", "underscore.string": "~2.2.1", "which": "~1.0.5", "js-yaml": "~2.0.5", "exit": "~0.1.1", "getobject": "~0.1.0", "grunt-legacy-util": "~0.2.0", "grunt-legacy-log": "~0.1.0"
/lib/grunt.js
. It "builds" and exports the grunt
object, connects the internal project libraries from /lib/grunt/*.js
: ... // Grunt -> export var grunt = module.exports = {}; ... // grunt function gRequire(name) { return grunt[name] = require('./grunt/' + name); } // gRequire('template'); ... // (alias) grunt function gExpose(obj, methodName, newMethodName) { grunt[newMethodName || methodName] = obj[methodName].bind(obj); } // registerTask task grunt gExpose(task, 'registerTask'); ...
tasks
method is added to the object, which is subsequently called from the CLI: grunt.tasks = function(tasks, options, done) { ... if (option('version')) { // show version return; } ... if(option('help')) { // show help return; } ... // , 'default' // task -> /lib/grunt/task.js var tasksSpecified = tasks && tasks.length > 0; tasks = task.parseArgs([tasksSpecified ? tasks : 'default']); ... // // , `grunt {TASK_1} {TASK_2}` tasks.forEach(function(name) { task.run(name); }); // task.start({asyncDone:true}); };
grunt.cli()
method, this method goes in the set of internal libraries /lib/grunt/*.js
, its task is to parry the transferred tasks and options and run grunt.tasks()
: ... var nopt = require('nopt'); ... // cli() var cli = module.exports = function(options, done) { if (options) { // ... } // grunt.tasks(cli.tasks, cli.options, done); }; ... // var optlist = cli.optlist = { help: { short: 'h', info: 'Display this help text.', type: Boolean } ... }; ... // var parsed = nopt(known, aliases, process.argv, 2); cli.tasks = parsed.argv.remain; cli.options = parsed;
Grunt
. The task for him is just a function that needs to be called at the right moment. grunt.registerTask('foo', function(a, b) { console.log(a, b); }); // > grunt foo // > undefined undefined // > grunt foo:bar:baz // > bar baz // : /lib/util.task.js -> task.init() -> task._taskPlusArgs() -> task.splitArgs()
Grunt
tasks, the internal library /lib/grunt/task.js and the utilities library /lib/util/task.js are used , look at the registerTask
method: ... // "" "task" util lib. var parent = grunt.util.task.create(); // var task = module.exports = Object.create(parent); ... task.registerTask = function(name) { ... // .registerTask() // {name: name, info: info, fn: fn} // task._tasks parent.registerTask.apply(task, arguments); // var thisTask = task._tasks[name]; // var _fn = thisTask.fn; thisTask.fn = function(arg) { ... // , ... // return _fn.apply(this, arguments); }; return task; };
Grunt
allows us to declare tasks using the registerMultiTask
method. Its only difference from registerTask
is that Grunt
will search for a property with the same name as the task name in the grunt.initConfig({})
config, which specifies various configurations (targets) and data to be executed: // Gruntfile.js grunt.initConfig({ log: { bar: [1, 2, 3], baz: 'hello world' } }); grunt.registerMultiTask('foo', function() { grunt.log.writeln(this.target + ': ' + this.data); }); // > grunt foo // > Running "foo:bar" (foo) task // > bar: 1,2,3 // > Running "foo:baz" (foo) task // > baz: hello world // > grunt foo:bar // > Running "foo:bar" (foo) task // > bar: 1,2,3
task.registerMultiTask = function(name, info, fn) { ... var thisTask; task.registerTask(name, info, function(target) { // () if (!target || target === '*') { return task.runAllTargets(name, this.args); } else if (!isValidMultiTaskTarget(target)) { throw new Error('Invalid target "' + target + '" specified.'); } // `name` this.requiresConfig([name, target]); // {name: target} // /lib/grunt/config.js -> .get() -> .getRow() this.data = grunt.config([name, target]); // return fn.apply(this, this.args); }); thisTask = task._tasks[name]; thisTask.multi = true; };
Grunt
one of a kind and there are no alternatives to it. But it is safe to say that he won popularity and authority. It is easy to install, quickly configured, has an attractive declarative style of configuring tasks, a rather βmodularβ structure of the project.Grunt
is now and what it is going to be. I hope the article turned out to be at least a little interesting and helped to look deeper at the tool that we use so often.Source: https://habr.com/ru/post/230753/
All Articles