class AsyncPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync('plugin', (comliation, cb) => {
setTimeout(() => {
console.log('等一等')
cb()
}, 1000)
})
compiler.hooks.emit.tapPromise('plugin', (comliation) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('promise')
resolve()
}, 1000)
})
})
}
}
module.exports = AsyncPlugin
输出列表及对应大小md
class FileListPlugin {
constructor({filename}) {
this.filename = filename
}
apply(compiler) {
// 文件准备好了要进行发射
compiler.hooks.emit.tap('plugin', (compilation) => {
let assets = compilation.assets
let content = `## 文件名 资源大小\r\n`
Object.entries(assets).forEach(([filename, statObj]) => {
content += `- ${filename} ${statObj.size()}\r\n`
})
assets[this.filename] = {
source() {
return content
},
size() {
return content.length
}
}
})
}
}
module.exports = FileListPlugin
把js css 都内嵌至html文件中
new InlineSourcePlugin({
match: /\.(js|css)/
}),
// 内联资源 css 使用style标签 js 都放在内部
const HtmlWebpackPlugin = require('html-webpack-plugin')
const pluginName = 'InlineSourcePlugin'
class InlineSourcePlugin {
constructor({match}) {
this.reg = match // 正则
}
apply(compiler) {
// 通过 html-webpackplugin 实现这个功能
// compilation 当前编译的资源
compiler.hooks.compilation.tap(pluginName, compilation => {
HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(pluginName, (data, cb) => {
// 当前文件的内容都在 compilation 中
// 虚拟dom
data = this.processTags(data, compilation)
cb(null, data)
})
})
}
processTags(data, compilation) {
// 处理引入标签的数据
let headTags = []
let bodyTags = []
// 放在head里面的标签
data.headTags.forEach(headTag => {
headTags.push(this.processTag(headTag, compilation))
})
data.bodyTags.forEach(bodyTag => {
bodyTags.push(this.processTag(bodyTag, compilation))
})
return {
...data, headTags, bodyTags
}
}
// 处理某一个标签
processTag(tag, compilation) {
console.log(tag)
let newTag, url
if (tag.tagName === 'link' && this.reg.test(tag.attributes.href)) {
newTag = {
tagName: 'style',
attributes: { type: 'text/css'}
}
url = tag.attributes.href
}
if (tag.tagName === 'script' && this.reg.test(tag.attributes.src)) {
newTag = {
tagName: 'style',
attributes: { type: 'application/javascript' }
}
url = tag.attributes.src
}
if (url) {
// 理解为 虚拟dom, 有tag 的属性
newTag.innerHTML = compilation.assets[url].source() // 文件内容 放到innerhtml属性中
// 处理完文件后 删除 文件
delete compilation.assets[url]
return newTag
}
return tag
}
}
module.exports = InlineSourcePlugin
上传 插件
new UploadPlugin({
bucket: '',
domain: '',
accessKey: '',
secretKey: ''
})
let path = require('path')
let qiniu = require('qiniu')
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) {
let localFile = path.resolve(__dirname, '../dist',filename)
return new Promise((resolve, reject) => {
this.formUploader.putFile(this.uploadToken, filename, localFile, this.putExtra, function(respErr, respBody, respInfo) {
if (respErr) {
reject(respErr)
}
if (respInfo.statusCode == 200) {
resolve(respBody)
}
})
})
}
}
module.exports = UploadPlugin