zoukankan      html  css  js  c++  java
  • webpack 插件怎么写

    摘要

    现在项目大部分都使用webpack 进行编译,一方面 webpack 生命力比较旺盛,另一方面 webpack 的生态非常完善。我们90%的场景都能够满足。但有时候也会遇到一些特定的业务场景,比如有时候会遇到需要对编译后的文件进行一些文件注入 等其他特定化的需求。怎么办呢?那就来写一个业务定制化的webpack 插件吧。

    官方文档可见: https://webpack.js.org/contribute/writing-a-plugin/#creating-a-plugin

    如何编写插件

    首先我们了解下一个插件的主要结构

    class DtoolPlugin {
        // 构造函数,进行参数校验等功能
        constructor(args) {}
        
        // 定义插件执行的方法体,主要逻辑都在这里完成,webpack 会自动调用此方法
        apply(compiler) {}
    
    }
    

    下面我们来看下 compiler 这个关键对象,compile 提供了 webpack 一系列操作的钩子函数,下面说一说常用的hooks

    官方文档可见:https://webpack.js.org/api/compiler-hooks/#watching

    下面以真实案例来讲解

    	apply(compiler) {
                const metaParams = this.metaParams;
    	    const tester = {test: this.test};
    
    	    compiler.hooks.compilation.tap('DtoolPlugin', (compilation) => {
                    compilation.hooks.optimizeChunkAssets.tapAsync('DtoolPlugin', (chunks, done) => {
                        wrapChunks(compilation, chunks);
                        done();
                    })
                });
                // 注入文件方法
                function wrapChunks(compilation, chunks) {
                    chunks.forEach(chunk => {
                        const args = {
                            hash: compilation.hash,
                            chunkhash: chunk.hash
                        };
                        chunk.files.forEach(fileName => {
                            if (ModuleFilenameHelpers.matchObject(tester, fileName)) {
                                const content = 'xxxxx';
                                // 注入内容
                                // assets 对象是编译后的对象,以文件名为key , 值为文件内容 、 文件size 等一系列信息, 通过asset 可以对文件名字 , 文件内容做变更
                                compilation.assets[fileName] = new ConcatSource(
                                    compilation.assets[fileName],
                                    String(content),
                                );
                        }
                    });
                });
            }
        }
    
    

    hooks 调用的时候有个类型 plugin types 支持 tap , 有些支持异步类型 tapAsync tapPromise

    compiler.hooks.run.tapAsync('MyPlugin', (source, target, routesList, callback) => {
      console.log('Asynchronously tapping the run hook.');
      callback();
    });
    
    compiler.hooks.run.tapPromise('MyPlugin', (source, target, routesList) => {
      return new Promise(resolve => setTimeout(resolve, 1000)).then(() => {
        console.log('Asynchronously tapping the run hook with a delay.');
      });
    });
    
    compiler.hooks.run.tapPromise('MyPlugin', async (source, target, routesList) => {
      await new Promise(resolve => setTimeout(resolve, 1000));
      console.log('Asynchronously tapping the run hook with a delay.');
    });
    
    
  • 相关阅读:
    linux常用命令
    Hibernate常用API以及使用说明
    Hibernate使用套路,新手请进
    git 完全讲解 无废话,包含在myeclipse中使用,包括解决冲突
    Spring使用事务增加的注解实现方
    java.lang.ClassCastException: com.sun.proxy.$Proxy27 cannot be cast to com.bbk.n002.service.QuestionService
    使用aspectJ实现Spring AOP的两种方式
    用Diff和Patch工具维护源码
    opennebula 补丁制作与补丁升级
    IPMI总结
  • 原文地址:https://www.cnblogs.com/huxiaoyun90/p/10721779.html
Copyright © 2011-2022 走看看