插件向第三方开发者提供了webpack引擎中完整的能力。使用阶段式的构建回调,开发者可以引入他们自己的行为到webpack构建流程中。创建插件比创建loader更加高级。

为什么需要一个插件

  • webpack基础配置无法满足需求
  • 插件几乎能够任意更改webpack编译结果
  • webpack内部也是通过大量的内部插件实现的

创建插件

  • 插件是一个类
  • 类上有一个apply的实例方法
  • apply的参数是compiler

    1. class [ClassName] {
    2. constructor(options) {
    3. this.otpions = options;
    4. }
    5. apply(compiler){
    6. ...
    7. }
    8. }

compiler和compilation的区别

compiler 对象代表了完整的webpack环境配置,这个对象在启动webpack时被一次性建立,并配置好所有的可操作性设置,包括options,loader和plugin,当在webpack环境中应用一个插件时候,插件将受到此compiler的引用,可以使用它来访问webpack的主环境

compilation 对象代表了一次资源版本的构建,当运行webpack开发环境中间件时,每当检测到一个文件的变化,就会创建有一个新的compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。

简单的自定义插件

done-plugin.js 编译结束执行的插件

  1. class DonePlugin {
  2. constructor(options) {
  3. this.options = options;
  4. }
  5. apply(compier) {
  6. compiler.hooks.done.tap('DonePlugin', () => {
  7. console.log('DonePlugin')
  8. })
  9. }
  10. }

image.png

Assets-plugin.js 打印资源块 和 对应文件名

  1. class AssetsPlugin {
  2. constructor(options) {
  3. this.options = options;
  4. }
  5. apply(compiler) {
  6. compiler.hooks.compilation.tap('AssetsPlugin', (compilation) => {
  7. compilation.hooks.chunkAssets.tap('AssetsPlugin', (chunk, filename) => {
  8. console.log('chunk, filename)
  9. });
  10. })
  11. }
  12. }
  13. module.exports = AssetsPlugin

image.png

Archive-plugin.js 把打包出来的文件做一个压缩包的备份

  1. const JSZip('jszip');
  2. class ArchivePlugin {
  3. constructor(options){
  4. this.options = options;
  5. }
  6. apply(compiler) {
  7. compiler.hooks.emit.tapPromise('ArchivePlugin', (compilation) => {
  8. // 本次编译出来的静态资源文件
  9. let assets = compilation.assets;
  10. let zip = new JSZip();
  11. for (let filename in assets) {
  12. // 获取文件对应的源代码
  13. const source = assets[filename].source();
  14. // 向压缩包添加文件,文件名是filename,文件内容是source
  15. zip.file(filename, source);
  16. }
  17. return zip.generateAsync({type: 'nodebuffer'}).then(content => {
  18. // 向输出的文件列表中添加一个新的文件
  19. assets['Archive_' + Date.now() + '.zip'] = {
  20. source() {
  21. return content
  22. }
  23. };
  24. })
  25. });
  26. }
  27. }
  28. module.exports = ArchivePlugin;