webpack系列-plugin

plugin简介

plugin的本质是一个类,类里面有一个apply方法,apply的参数为compiler,在其上面会有一些hooks,不同的hooks对应不同的tapable实例。

同步和异步的生命周期的plugin

webpack打包完毕触发的hooks

    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引入的方式变成内联的样式。

   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;
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值