思路:注册webpack插件 打包后执行 指定的函数


webpack插件组成:

  • 一个具名 JavaScript 函数;
  • 在它的原型上定义 apply 方法;
  • 指定一个触及到 Webpack 本身的事件钩子
  • 操作 Webpack 内部的实例特定数据;
  • 在实现功能后调用 Webpack 提供的 callback。


插件由一个构造函数实例化出来。构造函数定义 apply 方法,在安装插件时,apply 方法会被 Webpack compiler 调用一次。apply 方法可以接收一个 Webpack compiler 对象的引用,从而可以在回调函数中访问到 compiler 对象。


MyPlugin.js

const fs = require('fs')

class MyPlugin {
  apply (compiler) {
    // 在 Webpack 打包完成时触发 `hooks.done`
    compiler.hooks.done.tap('MyPlugin', () => {
      console.log('MyPlugin 插件运行完成.')
      console.log('是生产环境吗', isProduction)
      if (!isProduction) return
      // 复制文件
      fs.copyFileSync('./dist/index.html', './dist/index3.html')
      // 删除文件
      // fs.unlinkSync('./dist/index.html')
    })
  }
}

module.exports = MyPlugin

3.3 选择插件触发时机

compiler.hooks.xx

选择插件触发时机,其实是选择插件触发的 compiler 钩子(即何时触发插件)。
Webpack 提供钩子有很多,这里简单介绍几个,完整具体可参考文档《Compiler Hooks》:

  • entryOption : 在 webpack 选项中的 entry 配置项 处理过之后,执行插件。
  • afterPlugins : 设置完初始插件之后,执行插件。
  • compilation : 编译创建之后,生成文件之前,执行插件。。
  • emit : 生成资源到 output 目录之前。
  • done : 编译完成。


compiler.hooks.done.xxx

在 compiler.hooks 下指定事件钩子函数,便会触发钩子时,执行回调函数。
Webpack 提供三种触发钩子的方法:

  • tap :以同步方式触发钩子;
  • tapAsync :以异步方式触发钩子;
  • tapPromise :以异步方式触发钩子,返回 Promise;

这三种方式能选择的钩子方法也不同,由于 compilation 是 SyncHook 同步钩子,所以采用 tap 触发方式。
tap 方法接收两个参数:插件名称和回调函数。

vue.config.js

const { defineConfig } = require('@vue/cli-service')
const MyPlugin = require('./MyPlugin.js')

module.exports = defineConfig({
  transpileDependencies: true,
  chainWebpack: config => {
    config.plugin('my-plugin')
      .use(MyPlugin)
  }
})

为什么不写在webpack.config.js中?

在使用 vue-cli 创建的项目中,默认情况下没有配置文件来控制Webpack配置项,而是使用了 vue.config.js 文件作为整个Vue CLI项目的配置入口。

如果你想显式地操作 Webpack 配置,则可以在 vue.config.js 文件中使用 chainWebpack 或者其它相关函数编程方式来自定义Webpack 配置。

也就是说,在使用 vue-cli 的过程中确实不会直接使用 webpack.config.js 文件, 但是你仍可以利用 Vue CLI 提供的灵活性和可扩展性编写Webpack 配置。


如果是使用的webpack

const MyPlugin = require('./MyPlugin.js')

module.exports = {
  plugins: [new MyPlugin()]
}