webpack 手写插件流程

2,046 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

引言

继上一篇 webpack手写loader流程 继续完成webpack手写plugin的流程
需要有一定的webpack基础

插件介绍

相比于loader,plugin拥有更宽的能力范围,它几乎能触及到webpack工作的每一个环节
原理:plugin通过勾子机制实现
在webpack工作的过程中,会有很多个环节,为了便于插件的扩展,webpack几乎为每一个环节都埋下了一个勾子,开发插件时,就可以往这些节点上挂载不同的任务,以扩展webpack的能力

WX20220606-110255@2x.png

webpack具体有哪些勾子:

WX20220606-115240@2x.png
官网勾子链接
并且webpack要求plugin必须是一个函数或者是一个包含apply方法的对象

开始

做一个能去除webpack打包注释的插件

WX20220606-180426@2x.png

webpack.config.js基本结构忽略,基本结构可看上一篇webpack手写loader流程
在第一层目录新建myPlugin.js

// myPlugin.js
class MyPlugin{
  // compiler => webpack配置对象
  apply(compiler){
    console.log('MyPlugin 启动')
    // 调用emit勾子,挂载函数
    // compilation => 此次打包的上下文
    compiler.hooks.emit.tap('MyPlugin', compilation => {
      // 遍历资源文件信息
      // 键name为每个资源的名称
      for(const name in compilation.assets){
        // console.log(name)
        if(name.endsWith('.js')){
          // 每个资源的值
          const contents = compilation.assets[name].source()
          const withoutComments = contents.replace(/\/\*\*+\*\//g,'')
          // 覆盖原始对象
          compilation.assets[name] = {
            source: () => withoutComments,
            size: () => withoutComments.length
          }
        }
      }
    })
  }
}

module.exports = MyPlugin

webpack.config.js

const MyPlugin = require('./myPlugin')

plugins: [
  ...
  new MyPlugin()
],

解读:

  1. apply方法接受一个compiler对象参数,该对象就是webpack工作中最核心的一个对象,它包含了此次构建过程中所有的配置信息,并且我们也通过它来注册我们的勾子函数
  2. 此次选择了emit勾子,因为去掉注释需要bundle.js里的代码已生成 WX20220606-180949@2x.png
  3. 遍历资源文件compilation.assets,name为每个资源的名称
    c0e1ac2061384f8eb1d10751975a7e4e_tplv-k3u1fbpfcp-watermark.png
  4. 拿到对应名称的资源compilation.assets[name].source(),然后做全局注释的替换replace
  5. 最后在覆盖回assets的原有属性,source和size

自此,myPlugin就算完成
效果:
WX20220606-190758@2x.png

总结

webpack还有很多其他的勾子,可以实现很多其他我们想要的功能,详细可以到webpack官网查看
--配图椰香大芒果

往期精彩文章

🌟两种方式轻松做react css样式隔离
🌟彻底理解redux的中间件原理
🌟canvas实现刮刮奖效果
🌟前端实现pdf下载
🌟web前端性能优化(全汇总)
🌟一句话概括this指向问题
🌟MutationObserver 实现微任务原理分析
🌟遇到几次的大厂笔试题:装饰数组push方法
🌟V8垃圾回收策略与GC算法
🌟浏览器缓存策略(强缓存和协商缓存)
🌟$nextTick 源码解读与原理分析
🌟手动封装适合react hook使用的状态管理工具