webpack系列-plugin

plugin簡介

plugin的本質是一個類,類裏面有一個apply方法,apply的參數爲compiler,在其上面會有一些hooks,不一樣的hooks對應不一樣的tapable實例。css

同步和異步的生命週期的plugin

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;
複製代碼
相關文章
相關標籤/搜索