1. class AsyncPlugin {
  2. apply(compiler) {
  3. compiler.hooks.emit.tapAsync('plugin', (comliation, cb) => {
  4. setTimeout(() => {
  5. console.log('等一等')
  6. cb()
  7. }, 1000)
  8. })
  9. compiler.hooks.emit.tapPromise('plugin', (comliation) => {
  10. return new Promise((resolve, reject) => {
  11. setTimeout(() => {
  12. console.log('promise')
  13. resolve()
  14. }, 1000)
  15. })
  16. })
  17. }
  18. }
  19. module.exports = AsyncPlugin

输出列表及对应大小md

  1. class FileListPlugin {
  2. constructor({filename}) {
  3. this.filename = filename
  4. }
  5. apply(compiler) {
  6. // 文件准备好了要进行发射
  7. compiler.hooks.emit.tap('plugin', (compilation) => {
  8. let assets = compilation.assets
  9. let content = `## 文件名 资源大小\r\n`
  10. Object.entries(assets).forEach(([filename, statObj]) => {
  11. content += `- ${filename} ${statObj.size()}\r\n`
  12. })
  13. assets[this.filename] = {
  14. source() {
  15. return content
  16. },
  17. size() {
  18. return content.length
  19. }
  20. }
  21. })
  22. }
  23. }
  24. module.exports = FileListPlugin

把js css 都内嵌至html文件中

  1. new InlineSourcePlugin({
  2. match: /\.(js|css)/
  3. }),
  4. // 内联资源 css 使用style标签 js 都放在内部
  5. const HtmlWebpackPlugin = require('html-webpack-plugin')
  6. const pluginName = 'InlineSourcePlugin'
  7. class InlineSourcePlugin {
  8. constructor({match}) {
  9. this.reg = match // 正则
  10. }
  11. apply(compiler) {
  12. // 通过 html-webpackplugin 实现这个功能
  13. // compilation 当前编译的资源
  14. compiler.hooks.compilation.tap(pluginName, compilation => {
  15. HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapAsync(pluginName, (data, cb) => {
  16. // 当前文件的内容都在 compilation 中
  17. // 虚拟dom
  18. data = this.processTags(data, compilation)
  19. cb(null, data)
  20. })
  21. })
  22. }
  23. processTags(data, compilation) {
  24. // 处理引入标签的数据
  25. let headTags = []
  26. let bodyTags = []
  27. // 放在head里面的标签
  28. data.headTags.forEach(headTag => {
  29. headTags.push(this.processTag(headTag, compilation))
  30. })
  31. data.bodyTags.forEach(bodyTag => {
  32. bodyTags.push(this.processTag(bodyTag, compilation))
  33. })
  34. return {
  35. ...data, headTags, bodyTags
  36. }
  37. }
  38. // 处理某一个标签
  39. processTag(tag, compilation) {
  40. console.log(tag)
  41. let newTag, url
  42. if (tag.tagName === 'link' && this.reg.test(tag.attributes.href)) {
  43. newTag = {
  44. tagName: 'style',
  45. attributes: { type: 'text/css'}
  46. }
  47. url = tag.attributes.href
  48. }
  49. if (tag.tagName === 'script' && this.reg.test(tag.attributes.src)) {
  50. newTag = {
  51. tagName: 'style',
  52. attributes: { type: 'application/javascript' }
  53. }
  54. url = tag.attributes.src
  55. }
  56. if (url) {
  57. // 理解为 虚拟dom, 有tag 的属性
  58. newTag.innerHTML = compilation.assets[url].source() // 文件内容 放到innerhtml属性中
  59. // 处理完文件后 删除 文件
  60. delete compilation.assets[url]
  61. return newTag
  62. }
  63. return tag
  64. }
  65. }
  66. module.exports = InlineSourcePlugin

上传 插件

  1. new UploadPlugin({
  2. bucket: '',
  3. domain: '',
  4. accessKey: '',
  5. secretKey: ''
  6. })
  7. let path = require('path')
  8. let qiniu = require('qiniu')
  9. class UploadPlugin {
  10. constructor(options) {
  11. let { bucket = '', domain = '', accessKey = '', secretKey = '' } = options
  12. let mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
  13. let putPolicy = new qiniu.rs.PutPolicy({ scope: bucket })
  14. this.uploadToken = putPolicy.uploadToken(mac)
  15. let config = new qiniu.conf.Config()
  16. this.formUploader = new qiniu.form_up.FormUploader(config)
  17. this.putExtra = new qiniu.form_up.PutExtra()
  18. }
  19. apply(compiler) {
  20. compiler.hooks.afterEmit.tapPromise('uploadPlugin', compilation => {
  21. let assets = compilation.assets
  22. let promises = []
  23. Object.keys(assets).forEach(filename => {
  24. promises.push(this.upload(filename))
  25. })
  26. return Promise.all(promises)
  27. })
  28. }
  29. upload(filename) {
  30. let localFile = path.resolve(__dirname, '../dist',filename)
  31. return new Promise((resolve, reject) => {
  32. this.formUploader.putFile(this.uploadToken, filename, localFile, this.putExtra, function(respErr, respBody, respInfo) {
  33. if (respErr) {
  34. reject(respErr)
  35. }
  36. if (respInfo.statusCode == 200) {
  37. resolve(respBody)
  38. }
  39. })
  40. })
  41. }
  42. }
  43. module.exports = UploadPlugin