webpack3.x中html-webpack-plugin插件处理模板html手动引入script加版本号问题

这个需求呢是我为了防止浏览器缓存我们的js,css文件,所以需要在引入的js最后加上版本号,以便文件改变之后可以重新下载, 处理方式: 需要对插件html-webpack-plugin进行拦截封装,代码如下

var config = require('../config'),
    md5 = require('md5'),
    glob = require('glob'),
    path = require('path'),
    fs = require('fs')


// globPath  比如:"../release/static/js/libs/**/*.js" 意思是读取该路径下的所有js文件
// 返回值是一个json对象 类似于{ 'static/js/libs/axios/axios.min.js': 'static/js/libs/axios/axios.min.js?279e63262790dc6457b60db2b9b6c1eb',
//   'static/js/libs/meta/meta.js': 'static/js/libs/meta/meta.js?3b0873df1bac2aae5f0fc9e0d3734b4e',
//   'static/js/libs/vue/vue.min.js': 'static/js/libs/vue/vue.min.js?07b2df13d2459234b86ae48a2571ce97',
//   'static/js/libs/zepto/fx.js': 'static/js/libs/zepto/fx.js?01bab604900377119718a0b0bbdf6918',
//   'static/js/libs/zepto/zepto.js': 'static/js/libs/zepto/zepto.js?e8e177218b50197e04135c1780ead0a1',
//   'static/js/libs/zepto/zepto.min.js': 'static/js/libs/zepto/zepto.min.js?f8ba791e88cb12532a59393f9e4298b0' }这样

function getStaticFile(globPath) {
    let entries = {}
    /**
     * 读取某个目录,并进行路径裁剪
     */
    glob.sync(globPath).forEach(function (entry) {
        let pathSplit = entry.split('/')
        for (let i = 0; i < pathSplit.length; i++) {
            if ("static" === pathSplit[i]) {
                let md5HashFile, pathKey = pathSplit.splice(i).join("/").replace(/static\//g, '')
                entries[pathKey] = pathKey + "?" + md5(fs.readFileSync(entry))
            }
        }
    });
    return entries;
}

// 对象合并函数
function Merge(target) {
    for (let i = 1, j = arguments.length; i < j; i++) {
        let singleData = arguments[i] || {};
        for (let key in singleData) {
            if (singleData.hasOwnProperty(key)) {
                let value = singleData[key]
                if (value !== undefined) {
                    target[key] = value
                }
            }
        }
    }
    return target
}

function resolve(str) {
    return path.resolve(__dirname, str)
}

function DefineResolvePlugin(options) {
    // Configure your plugin with options...
    this.options = options.options
}
let fileObj = Merge({}, getStaticFile(resolve("../release/static/js/lib/**/*.js")), getStaticFile(resolve("../release/static/js/modules-v2/**/*.js")), getStaticFile(resolve("../release/static/css/**/*.css")))

DefineResolvePlugin.prototype.apply = function (compiler) {
    const htmlNotes = this.options.htmlNotes
    compiler.plugin('emit', function (compilation, callback) {
        for (let filename in compilation.assets) {
            (function (filename) {
                let tem = compilation.assets[filename].source();
                // if (!/\.(png|jpe?g|gif|svg|ico|woff2?|eot|ttf|otf)(\?.*)?$/.test(tem)) {
                if (/\.(js|html)(\?.*)?$/.test(tem)) {
                    // console.log(tem)
                    compilation.assets[filename] = {
                        source: function () {
                            if (fileObj) {
                                for (let key in fileObj) {
                                    let element = fileObj[key]
                                    let reg = new RegExp(key.replace(/\./g, '\.'), "gim")
                                    if (reg.test(tem)) {
                                        tem = tem.replace(/(\.\.\/)+/g, config.build.assetsPublicPath).replace(reg, element)
                                    }
                                }
                            }
                            return tem.replace(/static\//gm, '');
                        },
                        size: function () {
                            return 1;
                        }
                    };
                }
            })(filename)
        }
        callback();
    });
    compiler.plugin('compilation', function (compilation) {
        compilation.plugin('html-webpack-plugin-after-html-processing', function (htmlPluginData, callback) {
            // 增加头部注释专用
            htmlPluginData.html = htmlNotes + htmlPluginData.html.toString()
            callback(null, htmlPluginData);
        });
    });
}


module.exports = DefineResolvePlugin;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

console.log(htmlPluginData)的数据如下

webpack

对其中的key为html拿到他的value值进行处理之后才传入callback回调函数处理,这样便可以如期替换相对路径成绝对地址并且加上版本号

处理之后的结果

webpack