webpack plugn 插件原理

从上文提炼出 webpack 的一些主要流程

init => run(前两个一般不用) => compile(编译开始的时候) => compilation(准备编译的整个过程) => make(开始编译) => afterCompile(编译结束) => seal(对代码进行封装,比如优化、合并...) => codeGenerate(生成代码) => emit(发射,把文件写到硬盘里面) => done

插件,就是找个地方插进去

比如:imagemin-webpack-pluginclean-webpack-plugin

imagemin-webpack-plugin

  • 这是一个压缩图片的插件
  • 文件目录非常简单
  • 主要看 apply 这个函数
  • 根据看源码的步骤,跳过声明
  • 直接看最后的 if else,因为我们一般使用的是 webpack 4 以上的版本,所以进入 compiler.hooks 分支(见代码备注)
  • 发现他监听了 emit 这个事件
  • 直接看函数名字我们就能知道他的主要功能(优化项目中图片和其他外部图片)
  • 对 compilation.assets (此次编译的文件)进行 map 操作,用 testFunction 判断是否是图片文件,然后执行 optimizeImage 这个方法进行图片优化(这里用到了 imagemin 这个库)

这个插件非常简单

clean-webpack-plugin

  • 这是一个清理 webpack 的输出目录的插件
  • 分析这个插件之前,我们先思考如果我们要写这个插件,我们应该监听哪个钩子函数?如果是init 可能可以?但是有点不妥,因为有可能初始化的过程中会报错,这样就不会产生新的文件,所以就没有必要清除之前的文件
  • 很显然我们应该在 emit (写文件之前)去清理文件
  • 果然他也是在监听 emit,从而去执行 handleInitial 和 removeFiles(看函数名字就知道了,这俩函数逻辑非常简单,这里暂不分析了)
  • 但是细心的你肯定也发现了,为什么下面他还监听了 done?
  • 因为可能 emit 的时候也会产生一些垃圾、临时文件,所以也需要清理

ProvidePlugin

  • 这个插件主要用于注入全局变量,比如说每个文件都需要用到 JQuery,你需要每个文件都引入,
    用这个插件他会帮你自动引入,你直接用就好了
  • 使用方法很简单
  • 在选项中声明好,只要你用到了 $ 或者 JQuery,就会自动引入 JQuery
  • vue 同理

  • 同样,如果是我们写这个插件,我们应该监听哪个钩子函数?

  • 猜测应该是在 compilation 或者 make 阶段

  • 这个插件就不一样了,他主要监听的是 nft 的 parse 阶段
  • 我们来看这个 handle 函数做了什么
  • 遍历了 definition (就是选项哪个对象: {$: 'jquery', vue: [....]})
  • 分析所有的表达式(expression),如果你用到了哪些,就帮你直接在依赖中添加(等价于帮你自动 import)
  • 主要思路

正式因为插件可以在任何阶段进行魔改,所以 webpack 功能非常强大

常用插件

18个常用 webpack插件,总会有适合你的!

loader 与 plugin 的区别

loader 没啥问题,就是转换文件
它丰富了webpack本身(难道 loader 没有丰富 webpack 吗?)
针对是loader结束后(plugin 可以对任何阶段进行操作)
它并不直接操作文件(他可以直接操作文件,甚至可以删文件)
就这些修正

loader 比较简单,在 make 阶段中执行,单纯的文件转换过程,而 plugin 他是对 webpack 的功能进行拓展,他是基于事件机制,对 webpack 的每个阶段都可以进行介入,做一些功能(任何你想做的)。

如何自己写一个 plugin

  • 必须名声一个 class

  • 必须有一个 apply 函数,并且接受一个 compiler 参数

  • 接下来对某一个钩子进行监听,在写你的主要逻辑

  • 举例

  • 一个简单的在 done 之后打印一句话,和使用方法

  • 用到的主要知识

  • 对 webpack hooks 的了解

  • 对编译原理的了解

  • 对 chunk、hash、module、dep、factor 等概念的理解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章