zoukankan      html  css  js  c++  java
  • webpack(四)——webpack里面的plugin和loader的区别

    一 、区别:

     前面我们介绍了webpack里面的 loader  plugin ,这里来回顾一下:

      *  loader是文件加载器,能够加载资源文件,并对文件进行一些处理,如编译压缩 等,最终一起打包到指定的文件中。

      * plugin赋予了webpack各种灵活的功能,如打包优化资源管理环境变量注入等,目的是为了解决loader无法实现的功能

     从整体的运行机制上来看,如下图所示:

      从上图可以看出:

      *  loader运行在项目打包之前;

      * plugins运行在整个项目的编译时期;

     

     在Webpack运行的整个生命周期中会广播出许多事件,Plugin会监听这些事件,在合适的事件通过 webpack 提供的 api 改变输出结果。

    对于 loader 而言,它实质上是一个转换器,将A文件编译成B文件,操作的是 文件比如将A文件编译成B文件,单纯的是一个文件转换过程。

     

    二、编写loader

      在编写 loader 之前,我们需要先理解 loader 的本质,loader 的本质是一个函数,函数中的 this 作为上下文会被 webpack 填充,因此我们不能将  loader 为一个箭头函数。

      函数接受一个参数,这个参数为 webpack  传递给  loader 的文件源内容。

      函数中的  this 是 webpack  提供的对象,能够获取当前 loader  所需要的各种信息。

      函数中有异步操作或者是同步操作的时候,异步操作会通过 this.callback 返回,返回值要为 string 或者 Buffer

      代码如下:

    // 导出一个函数,source为webpack传递给loader的文件源内容
    module.exports = function(source) {
        const content = doSomeThing2JsString(source);
        
        // 如果 loader 配置了 options 对象,那么this.query将指向 options
        const options = this.query;
        
        // 可以用作解析其他模块路径的上下文
        console.log('this.context');
        
        /*
         * this.callback 参数:
         * error:Error | null,当 loader 出错时向外抛出一个 error
         * content:String | Buffer,经过 loader 编译后需要导出的内容
         * sourceMap:为方便调试生成的编译后内容的 source map
         * ast:本次编译生成的 AST 静态语法树,之后执行的 loader 可以直接使用这个 AST,进而省去重复生成 AST 的过程
         */
        this.callback(null, content); // 异步
        return content; // 同步
    }
    View Code

      注意:

      一般在做 loader  的功能装换的时候,保持功能单一,避免做多种功能。

     

    三、编写plugin

      由于 webpack 基于发布订阅模式,在运行的生命周期中会广播出许多事件,插件会通过监听这些事件,就可以在特定的阶段执行自己的插件任务。

     

      webpack 编译会创建两个核心对象:

      * compiler :包含了 webpack 环境所有的 配置信息,包括了 optionsloaderplugin和 webpack 整个生命周期有关的钩子。

      * compilation: 作为 plugin 内置事件回调函数的参数,包含了当前的 模块资源,编译生成资源,变化的文件 以及 被 跟踪的文件 的状态信息,当检测到了一个文件发生了改变的时候,就会生成一个新的 Compilation 对象。

     

      如果要创建自己的 plugin,也需要遵循一定的规范:

      * 插件必须是一个函数或者是一个包含了 apply 方法的对象,这样才能够访问 Compiler 对象。

      * 传给每一个插件的 compiler 和 compilation 对象都是同一个应用,因此不建议修改。

      * 异步的事件需要在插件处理完任务和调用回调函数通知 webpack 进入下一个流程,不然会卡住。
     
      
      实现 plugin 的模块如下:
    class MyPlugin {
        // Webpack 会调用 MyPlugin 实例的 apply 方法给插件实例传入 compiler 对象
      apply (compiler) {
        // 找到合适的事件钩子,实现自己的插件功能
        compiler.hooks.emit.tap('MyPlugin', compilation => {
            // compilation: 当前打包构建流程的上下文
            console.log(compilation);
            
            // do something...
        })
      }
    }

       

      在 emit 事件发生的时候,代表源文件的转换和组装已经完成,可以读取到最终将输出的 资源,代码块,模块,依赖,并且可以修改输出资源的内容

    转自:https://mp.weixin.qq.com/s/U5J6nCANyKx3olFTzRVr6g

  • 相关阅读:
    LuoguP2765 魔术球问题
    LuoguP1402 酒店之王
    luoguP4313 文理分科
    玲珑杯 1138
    codeforces 822 D. My pretty girl Noora(dp+素数筛)
    codeforces 822 C. Hacker, pack your bags!(思维+dp)
    51nod 1376 最长递增子序列的数量(不是dp哦,线段树 +  思维)
    hdu4565 So Easy!(矩阵快速幂)
    atcode E
    atcoder D
  • 原文地址:https://www.cnblogs.com/zhilili/p/14721434.html
Copyright © 2011-2022 走看看