plugin的本質是一個類,類裏面有一個apply方法,apply的參數爲compiler,在其上面會有一些hooks,不一樣的hooks對應不一樣的tapable實例。css
webpack打包完畢觸發的hookshtml
class DonePlugin{
apply(compiler){
compiler.hooks.done.tap('DonePlugin',()=>{
console.log('編譯完成')
})
}
}
class AsyncPlugin {
apply(compiler){
compiler.hooks.emit.tapAsync('AsyncPlugin',(compilation,cb)=>{
setTimeout(()=>{
cb()
},1000)
)
compiler.hooks.emit.tapPromise('AsyncPlugin',(compilation)=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve()
},1000)
})
)
}
}
// 使用
plugins:[
new DonePlugin(),
new AsyncPlugin()
]
複製代碼
class FileListPlugin {
constructor(filename){
this.filename = filename;
}
apply(compiler){
compiler.hooks.emit.tap('FileListPlugin',(compilation)=>{
// 獲取全部打包的文件
let assets = compilation.assets
let content = `## 文件名 資源大小`;
// [[bundle.js,{}],[index.html,{}]]
Object.entries(assets).forEach([filename,statObj]=>{
content+= `- ${filename} ${statObj.size()}`
})
assets[this.filename] = {
source(){
return content
},
size(){
return content.length
}
}
})
}
}
// 使用
plugins:[
new FileListPlugin({
filename:'list.md'
})
]
複製代碼
將link或者script引入的方式變成內聯的樣式。webpack
let HtmlWebpackPlugin = require('html-webpack-plugin')
class InlineSourcePlugin {
constructor({match}){
this.match = match;
}
processTag(tag,compilation){
// 取出css路徑和js路徑
let url = tag.attributes.href || tag.attributes.src
if(this.match.test(url)){
// 修改css
if(tag.tagName === 'link'){
tag = {tagName:'style',
innerHTML:compilation.assets[url].source()
}
}
// 修改js
if(tag.tagName === 'script'){
tag = {tagName:'script',
innerHTML:compilation.assets[url].source()
}
}
delete compilation.assets[url]; // 從打包後的資源中刪除掉
}
return tag;
}
processTags(data,compilation){
let headTags = data.headTags;
let bodyTags = data.bodyTags;
headTags = headTags.map(tag=>{
return this.processTag(tag,compilation)
});
bodyTags = bodyTags.map(tag=>{
return this.processTag(tag,compilation)
});
return {...data,headTags,bodyTags}
}
apply (compiler) {
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
console.log('The compiler is starting a new compilation...')
HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(
'MyPlugin',
(data, cb) => {
data = this.processTags(data,compilation);
cb(null, data)
}
)
})
}
}
module.exports = InlineSourcePlugin;
// 使用
plugins:[
new InlineSourcePlugin({
match:/\.(js|css)$/
})
]
複製代碼
let qiniu = require('qiniu');
let path = require('path');
class UploadPlugin {
constructor(options = {}) {
let { bucket = '', domain = "", accessKey = '', secretKey = '' } = options;
let mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
let putPolicy = new qiniu.rs.PutPolicy({ scope: bucket });
this.uploadToken = putPolicy.uploadToken(mac);
let config = new qiniu.conf.Config();
this.formUploader = new qiniu.form_up.FormUploader(config);
this.putExtra = new qiniu.form_up.PutExtra();
}
apply(compiler){
compiler.hooks.afterEmit.tapPromise('UploadPlugin',(compilation)=>{
let assets = compilation.assets;
let promises = [];
Object.keys(assets).forEach(filename=>{
promises.push(this.upload(filename));
});
return Promise.all(promises)
})
}
upload(filename) {
return new Promise((resolve,reject)=>{
let realPath = path.resolve(__dirname,'../dist',filename)
this.formUploader.putFile(this.uploadToken, filename, realPath, this.putExtra,(err,body)=>{
err?reject(err):resolve(body);
})
});
}
}
module.exports = UploadPlugin;
複製代碼