虽然很少会有这种需求,当我们需要最终输出的时候文件尽可能少的时候还是会用到。

var fs = require('fs');
var path = require('path');
var md5 = require('md5-file');
grunt.registerTask('hash', function(target) {
    var hash = Date.now();
    console.log('Hash:', hash);
    var files = grunt.file.expand({
        cwd: config.dist,
        filter: function(path) {
            return grunt.file.isFile(path);
        }
    }, ['**/*.html']);
    files.forEach(function(p) {
        var fullPath = config.dist + '/' + p;
        console.log('处理文件:', fullPath);
        var content = grunt.file.read(fullPath, 'utf8');
        //content = content.replace(/\{\{_version_\}\}/g, hash);
        var jsReg = /<\s*script\s+[^>]*?src\s*=\s*"([^"]+.js)[^>]*"[^>]*?><\s*\/\s*script\s*>/gi;
        var cssReg = /<\s*link\s+[^>]*?href\s*=\s*"([^"]+.css)[^>]*"[^>]*?>/gi;
        var removeReg = /http:|https:|\/\//; //远程url过滤正则
        if (target === 'inline') {
            content = content.replace(cssReg, function(a, b) {
                if (removeReg.test(b)) {
                    console.log('远程地址', b)
                    return a;
                }
                var text = fs.readFileSync(path.resolve(__dirname, 'build', b));
                return '<style type="text/css">' + text + '</style>';
            });
            content = content.replace(jsReg, function(a, b) {
                if (removeReg.test(b)) {
                    console.log('远程地址', b)
                    return a;
                }
                var text = fs.readFileSync(path.resolve(__dirname, 'build', b));
                return '<script>' + text + '</script>';
            });
        } else {
            content = content.replace(cssReg, function(a, b) {
                if (removeReg.test(b)) {
                    console.log('远程地址', b)
                    return a;
                }
                var hash = md5(path.resolve(__dirname, 'build', b));
                return '<link rel="stylesheet" href="' + b + '?_v=' + hash + '"/>';
            });
            content = content.replace(jsReg, function(a, b) {
                if (removeReg.test(b)) {
                    console.log('远程地址', b)
                    return a;
                }
                var hash = md5(path.resolve(__dirname, 'build', b));
                return '<script src="' + b + '?_v=' + hash + '"></script>';
            });
        }
        grunt.file.write(fullPath, content);
    });
});

使用示例:

grunt.registerTask('build', [
    'clean:dist',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'cssmin',
    'uglify',
    'copy:dist',
    //'rev',
    'usemin',/*,
    'htmlmin'*/
    'hash:inline'
  ]);