zoukankan      html  css  js  c++  java
  • webpack 自定义 plugin ?

    plugin 的本质 类 (构造函数)

    1 重要概念 tapable 类

    const {
    SyncHook, // 同步 执行
    SyncBailHook, // 同步执行,但是一旦有返回值,就执行退出,不再继续执行其他
    AsyncParallelHook, // 异步 并行执行
    AsyncSeriesBailHook, // 异步 串行执行
    } = require('tapable');

    class Lesson {
    constructor() {
    // 初始化 hook容器
    this.hooks = {
    // 同步钩子,任务会依次执行
    // go: new SyncHook(['address']),
    go: new SyncBailHook(['address']), // 一旦有返回值,就不会再往下执行了
    // 异步hooks
    // AsyncParallelHook 异步并行
    // leave: new AsyncParallelHook(['name', 'age']),
    leave: new AsyncSeriesBailHook(['name', 'age']),
    };
    }

    tap() {
    // 往hooks 容器中注册事件/ 添加回调函数
    this.hooks.go.tap('class001', (address) => {
    console.log('class001', address);
    return 111;
    });
    this.hooks.go.tap('class002', (address) => {
    console.log('class002', address);
    });

    this.hooks.leave.tapAsync('class003', (name, age, cb) => {
      setTimeout(() => {
        console.log('class003', name, age);
        cb();
      }, 2000);
    });
    this.hooks.leave.tapPromise('class004', (name, age) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log('class004', name, age);
          resolve();
        }, 1000);
      });
    });
    

    }

    start() {
    this.hooks.go.call('c318');
    this.hooks.leave.callAsync('zh', '18', () => {
    // 代表所有leave容器中的函数触发完了,才触发
    console.log('end');
    });
    }
    }
    const l = new Lesson();
    l.tap();
    l.start();

    
    
    ##### 2 complier 类
    拥有各种钩子函数
    ```js
    class Plugin1 {
      apply(complier) {
        complier.hooks.emit.tap('Plugin1', () => {
          console.log('emit 111111111111');
        });
    
        complier.hooks.afterEmit.tap('Plugin1', () => {
          console.log('emit after 111111111111');
        });
      }
    }
    module.exports = Plugin1;
    
    
    3 compilation 类 (通过compiler.hooks.thisCompilation 获取),可对文件进行操作
    const fs = require('fs');
    const util = require('util');
    const path = require('path');
    const { RawSource } = require('webpack-sources');
    // 将fs . readFile 的异步方法,改变成同步的写法
    const readFile = util.promisify(fs.readFile);
    class Plugin2 {
      apply(compiler) {
        // 初始化compilation 的钩子
        compiler.hooks.thisCompilation.tap('Plugin2', (compilation) => {
          // debugger;
          // console.log(compilation);
          compilation.hooks.additionalAssets.tapAsync('Plugin2', async (cb) => {
            const content = 'debug';
            // 往要输出资源中,添加一个a.txt
            compilation.assets['a.txt'] = {
              size() {
                return content.length;
              }, // 文件大小
              source() {
                return content;
              }, // 文件内容
            };
            const data = await readFile(path.resolve(__dirname, '../b.txt'));
            compilation.assets['b.txt'] = new RawSource(data);
            compilation.emitAsset('c.txt', new RawSource(data));
            cb();
          });
        });
      }
    }
    module.exports = Plugin2;
    

    自定义插件 - CopyWebpackPlugin

    const path = require('path');
    const fs = require('fs');
    const {promisify} = require('util')
    
    const { validate } = require('schema-utils');
    const globby = require('globby');
    const webpack = require('webpack');
    
    const schema = require('./schema.json');
    const { Compilation } = require('webpack');
    
    const readFile = promisify(fs.readFile);
    const {RawSource} = webpack.sources
    
    class CopyWebpackPlugin {
      constructor(options = {}) {
        // 验证options是否符合规范
        validate(schema, options, {
          name: 'CopyWebpackPlugin'
        })
    
        this.options = options;
      }
    
      apply(compiler) {
        // 初始化compilation
        compiler.hooks.thisCompilation.tap('CopyWebpackPlugin', (compilation) => {
          // 添加资源的hooks
          compilation.hooks.additionalAssets.tapAsync('CopyWebpackPlugin', async (cb) => {
            // 将from中的资源复制到to中,输出出去
            const { from, ignore } = this.options;
            const to = this.options.to ? this.options.to : '.';
            
            // context就是webpack配置
            // 运行指令的目录
            const context = compiler.options.context; // process.cwd()
            // 将输入路径变成绝对路径
            const absoluteFrom = path.isAbsolute(from) ? from : path.resolve(context, from);
    
            // 1. 过滤掉ignore的文件
            // globby(要处理的文件夹,options)
            const paths = await globby(absoluteFrom, { ignore });
    
            console.log(paths); // 所有要加载的文件路径数组
    
            // 2. 读取paths中所有资源
            const files = await Promise.all(
              paths.map(async (absolutePath) => {
                // 读取文件
                const data = await readFile(absolutePath);
                // basename得到最后的文件名称
                const relativePath = path.basename(absolutePath);
                // 和to属性结合
                // 没有to --> reset.css
                // 有to --> css/reset.css
                const filename = path.join(to, relativePath);
    
                return {
                  // 文件数据
                  data,
                  // 文件名称
                  filename
                }
              })
            )
    
            // 3. 生成webpack格式的资源
            const assets = files.map((file) => {
              const source = new RawSource(file.data);
              return {
                source,
                filename: file.filename
              }
            })
            
            // 4. 添加compilation中,输出出去
            assets.forEach((asset) => {
              compilation.emitAsset(asset.filename, asset.source);
            })
    
            cb();
          })
        })
      }
    
    }
    
    module.exports = CopyWebpackPlugin;
    
  • 相关阅读:
    一步步学习MDL[3]
    一步步学习MDL[0]
    .net下ckeditor+ckfinder+SyntaxHighlighter三集成demo
    页面跳转如何进入一个嵌套在Iframe中的页面中
    解决iframe,div在移动设备上实现局部刷新的方法
    SQL三种东西永远不要放到数据库里
    悟透JavaScript
    Js 常用日期汇总
    js_兼容IE和FF
    SQL中字符串类型转换为时间类型
  • 原文地址:https://www.cnblogs.com/honkerzh/p/14008076.html
Copyright © 2011-2022 走看看