《JavaScript开发框架权威指南》——2.6 创建Grunt插件
本节书摘来自异步社区《JavaScript开发框架权威指南》一书中的第2章,第2.6节,作者:【美】Tim Ambler , Nicholas Cloud着,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.6 创建Grunt插件
社区提供的丰富插件库是让Grunt真正变得闪耀的库,它能使你立即从Grunt中获益,而不是需要从头创建复杂的任务。如果你需要在项目中做自动构建,那么很可能某人已经为你做好这项“Grunt”工作。在这一节中,你可以懂得如何向社区回馈自己创建的Grunt插件。
2.6.1 开始
首先要做的事情之一是情创建一个公共的GitHub仓库,以存储你的新插件。下文中将要提及的示例包含在本书附带的源码中,本书附带了源码。一旦你准备好代码仓库,就把它克隆到你的电脑上。下一步,按照本章前面“将Grunt添加到项目中”一节所概述的步骤,在仓库目录中初始化Grunt。然后,你的新Grunt插件的文件模式将会类似清单中的示例。
清单2-31 新Grunt插件的文件模式
.
├── Gruntfile.js
├── README.md
├── package.json
├── tasks
注意:
这里提到的最重要一点是创建Grunt插件不需要任何额外的模式或知识(抛开本章已经涵盖的内容不说)。这个过程反映了把Grunt整合进一个现有的项目中,Gruntfile的建立用于加载任务,除此之外是任务本身。一旦插件发布至npm,其他的Grunt项目就能够像本章中到处提及的方式一样来加载你的插件。
2.6.2 创建任务
按照示例中的方式,让我们创建一个Grunt插件,该插件能够生成一份描述了项目中包含的文件类型、大小和数量的报告。该插件的配置示例如清单所示。
清单2-32 插件配置示例代码
// example-plugin/Gruntfile.js
module.exports = function(grunt) {
grunt.config('file-report', {
'options': {
},
'public': {
'src': ['public/**/*']
},
'images': {
'src': ['public/**/*.jpg', 'public/* */*.png', 'public/**/*.gif']
}
});
grunt.loadNpmTasks('grunt-file-reporter');
grunt.registerTask('default', ['file-report']);
};
从清单中可以看到插件的源码,其中Grunt注册了一个多任务file-report。每当调用这个任务,清单中指定的目标文件会被迭代遍历。完成这个任务后,插件会编译得到一个报告展示出它发现的文件类型、数量和大小详情。
清单2-33 插件的源码
// example-plugin/node_modules/grunt-file-reporter/Gruntfile.js
var fs = require('fs');
var filesize = require('filesize');
var _ = require('lodash');
_.mixin(require('underscore.string'));
module.exports = function(grunt) {
var mime = require('mime');
var Table = require('cli-table');
grunt.registerMultiTask('file-report', 'Generates a report of file types & sizes used
within a project ', function() {
var report = {
'mimeTypes': {},
'largest': null,
'smallest': null
};
var table = new Table({
'head': ['Content Type', 'Files Found', 'Total Size',
'Average Size', 'Largest', 'Smallest']
});
var addFile = function(file) {
if (grunt.file.isDir(file)) return;
var mimeType = mime.lookup(file);
if (!report.mimeTypes[mimeType]) {
report.mimeTypes[mimeType] = {
'count': 0,
'sizes': [],
'largest': null,
'smallest': null,
'oldest': null,
'newest': null
};
}
var details = report.mimeTypes[mimeType];
details.count++;
var stats = fs.statSync(file);
details.sizes.push(stats.size);
if (!details.largest || stats.size > details.largest.size) {
details.largest = { 'file': file, 'size': stats.size };
}
if (!report.largest || stats.size > report.largest.size) {
report.largest = { 'file': file, 'size': stats.size };
}
if (!details.smallest || stats.size < details.smallest.size) {
details.smallest = { 'file': file, 'size': stats.size };
}
if (!report.smallest || stats.size < report.smallest.size) {
report.smallest = { 'file': file, 'size': stats.size };
}
};
var sum = function(arr) {
return arr.reduce(function(a, b) {
return a + b;
});
};
var displayReport = function() {
var totalSum = 0;
var totalFiles = 0;
var totalSizes = [];
_.each(report.mimeTypes, function(data, mType) {
var fileSum = sum(data.sizes);
totalSum += fileSum;
totalFiles += data.sizes.length;
totalSizes = totalSizes.concat(data.sizes);
table.push([mType, data.count, filesize(fileSum),
filesize(fileSum / data.sizes.length),
_.sprintf('%s (%s)', data.largest.file, filesize(data.largest.size)),
_.sprintf('%s (%s)', data.smallest.file, filesize(data.smallest.size)),
]);
});
table.push(['-', totalFiles, filesize(totalSum),
filesize(totalSum / totalSizes.length),
_.sprintf('%s (%s)', report.largest.file, filesize(report.largest.size)),
_.sprintf('%s (%s)', report.smallest.file, filesize(report.smallest.size)),
]);
console.log(table.toString());
};
this.files.forEach(function(files) {
files.src.forEach(addFile);
});
displayReport();
});
};
由file-report插件生成的输出如图所示。
图2-1 file-report任务所生成的输出
2.6.3 将任务发布到npm
一旦我们的插件已经就绪并且我们的Git仓库也更新到最新的代码,最后一步就是通过npm发布插件使他人也可用。
$ npm publish
注意:
如果这是你第一次向npm发布模块,你将被要求创建一个账号。
最后更新:2017-06-06 07:33:03