举一反三。
准备工作
本文的工程环境承接上文
这个简单的工程目录如下:
- build
- node_modules
- package.json
- plugins
- 0.createLicense.js
- 1.createFileList.js
- 2.createLicense.js
- loaders
- src
- index.js
- LICENSE
简单分析
说起这个,也许你的思路是:
- 给HtmlWebpackPlugin传一个html模板,然后在模板里面改改
-
webpack.config.js:
plugins: [ new HtmlWebpackPlugin({ template: resolve('./src/index.html') }), new CreateLicensePlugin(), new FileListPlugin(), new AddRemarksPlugin(), ],
-
src/index.html:
<html lang="en"> <head> <!-- 模板本来就有的备注 --> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Webpack Plugin and Loader test</title> </head> <body> </body> </html>
-
- 上面那样行不通,因为资源会被进行优化,注释是会被过滤掉的。
我们可以任意选择一个靠后的时机,只要在optimizeAssets之后。
插件实现
const pluginName = 'AddRemarksPlugin';
class AddRemarksPlugin {
constructor(options = {}) {
this.remarks = options.remarks || '<!-- 这是一条由AddRemarksPlugin生成的默认备注 -->'
}
apply(compiler) {
const { hooks, options, webpack } = compiler;
const outputPath = options.output.path
compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
compilation.hooks.processAssets.tap({
name: pluginName,
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
}, (assets) => {
const htmlObj = assets['index.html']
if(htmlObj){
const raw = htmlObj._valueAsString
const start = raw.indexOf('<head>') + 6
const left = raw.substring(0, start)
const right = raw.substring(start)
const content = `${left}\n${this.remarks}\n${right}`
compilation.updateAsset(
'index.html',
new webpack.sources.RawSource(content)
);
}else{
console.error('不存在index.html!!!');
}
});
});
}
}
module.exports = AddRemarksPlugin;
源代码
https://github.com/nicennnnnnnlee/webpack-plugin-loader-examples