
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